関連概念#
- タプル:二次元テーブルにおいて、行はタプルと呼ばれます。リレーショナルデータベースにおいて、リレーションはテーブルであり、テーブルの各行(すなわちデータベース内の各レコード)はタプルであり、各列は属性です。
- キー:二次元テーブルにおいて、列はキーと呼ばれます。エンティティを一意に識別できる属性であり、テーブル内の列に対応します。
- 候補キー:リレーション内のある属性または属性の値がタプルを一意に識別でき、その任意の部分集合が識別できない場合、その属性の集合は候補キーと呼ばれます。例えば:学生テーブルにおいて、{学号} と {姓名,班级} はどちらも候補キーです。
- 主キー:主キーは候補キーから選ばれたものです。
- 外部キー:外部キー。あるリレーション内の属性が同時に別のリレーション内の主キーである場合、その属性は外部キーです。
- 主属性:候補キーに含まれる属性は主属性と呼ばれます。
- 非主属性:いかなる候補キーにも含まれない属性です。
drop、delete と truncate#
用法の違い#
タイプの違い#
- DML 言語:データベース操作言語(Data Manipulation Language)、データベースの追加、削除、更新、検索に関する言語
- DDL 言語:データ定義言語(Data Definition Language)、データベース内部オブジェクトの作成、削除、変更に関する言語で、データベース構造に関連します。
delete は DML 言語であり、実行後に delete 操作は rollback セグメントに置かれ、トランザクションがコミットされた後に有効になり、ロールバックも可能です。
drop と truncate は DDL 言語であり、実行後に即座に有効になり、データはロールバックできません。
実行速度の違い#
drop > truncate > delete
utf8 と utf8mb4#
-
utf8
:utf8
エンコーディングは1-3
バイトのみをサポートします- 中国語は 3 バイトを占め、他の数字、英語、記号は 1 バイトを占めます。
- emoji 記号は 4 バイトを占めるため、utf8 では emoji 記号を保存できません。
-
utf8mb4
: UTF-8 の完全な実装。最大で 4 バイトを使用して文字を表現できます。emoji 記号を保存するために使用できます。
データベースの正規化#
第一正規形 1NF#
原子性:データベース内の属性(データテーブルの列)は分割できません。
第二正規形 2NF#
第一正規形に基づき、テーブル内の各列は主キーに関連付けられるべきです。
同じテーブルに学生の基本情報と学生の成績を保存することは、第二正規形に違反します。
各テーブル内の非主属性は完全にキーに依存しています
第三正規形 3NF#
テーブル内の非主属性同士は互いに依存してはいけません
第二正規形に基づき、非主属性間の依存関係を排除し、非主属性とキーの依存関係のみを保持します。
MySQL データ型#
整数型#
tinyint
,smallint
,middleint
,int
,bigint
はそれぞれ 8、16、24、32、64 のストレージスペースを占有します。
浮動小数点数#
float
double
decimal
:高精度小数型。
これらの 3 種類の浮動小数点数は列幅を指定できます。例えば、decimal(18,9)
は合計 18 桁で、小数部分に 9 桁を保存し、残りを整数部分に保存します。
文字列#
char
:固定長で、末尾の空白を自動的に削除します。varchar
:可変長で、末尾の空白を削除しません。blog
:バイナリ形式で保存します。text
:文字列形式で保存します。
時間#
datatime
:1001 年から 9999 年までの日付と時間を保存し、精度は秒で、8 バイトのストレージスペースを使用し、タイムゾーン情報はありません。timestamp
:1970-01-01 からの時間を保存します。4 バイトで保存され、2038 年までしか表現できず、タイムゾーン情報があります。
MySQL 基盤構造#
MySQL ストレージエンジン#
show engines
コマンドを使用して MySQL のストレージエンジンを確認します。
一般的に使用されるのは InnoDB と MyISAM エンジンです。
デフォルトでは InnoDB エンジンが使用されます。
MyISAM#
- トランザクションをサポートしていません。
- 行レベルロックをサポートせず、テーブル全体にロックをかけることしかできません。読み取り時に共有ロックをかけ、書き込み時に排他ロックをかけます。
- データ損失のリスクがあります。
InnoDB#
- トランザクションをサポートし、4 つの分離レベルを実現し、デフォルトのレベルはリピート可能読み取りで、MVCC(多バージョン同時実行制御)+Next-KeyLocking(ギャップロック)を使用してファントムリードを防ぎます。
- 主インデックスはクラスタインデックスです。
MyISAM と InnoDB#
- ロック:MyISAM はテーブルレベルロックを使用し、InnoDB は行レベルロックを使用します。
- トランザクション:MyISAM はトランザクションをサポートせず、InnoDB はトランザクションをサポートします。
- 外部キー:MyISAM は外部キーをサポートせず、InnoDB は外部キーをサポートします。
- クラッシュリカバリ:MyISAM はクラッシュ後の安全なリカバリをサポートせず、InnoDB はログを通じてクラッシュ後の安全なリカバリをサポートします。
- インデックスの実装方法の違い:両者は B + ツリーのデータ構造を使用します。MyISAM ではインデックスファイルとデータファイルが分離されており、InnoDB ではデータファイルが同時にインデックスファイルでもあります。
MySQL トランザクション#
トランザクション:論理的な一連の操作であり、すべて実行されるか、すべて実行されないかのいずれかです。
トランザクションの特性#
- 原子性(Atomicity):トランザクションに含まれるすべての操作は、すべて成功するか、すべて失敗するかのいずれかです。
- 一貫性(Consistency):トランザクションの実行前後の状態が一貫していること。例えば、振込:振込が完了してもお金の総額は変わらない。
- 隔離性(Isolation):未コミットの読み取りが許可されるかどうか。
- 永続性(Durability):トランザクションがコミットされた後、データベースの変更は永続的です。
略して ACID
トランザクションが引き起こす問題#
- ダーティリード:未コミットのトランザクションが別のトランザクションの未コミットデータを読み取った。
- 不可再読:実行が遅いトランザクションがトランザクション中に 1 つのレコードを読み取り、2 回目に読み取ったデータが異なる。主に update と delete に関連します。
- ファントムリード:2 回の読み取りでデータの件数が異なる。insert に関連します。
トランザクションの分離レベル#
- (READ-UNCOMMITTED) 未コミットの読み取り:最低レベルで、未コミットのデータ変更を読み取ることを許可し、ダーティリード、不可再読、ファントムリードを引き起こす可能性があります。
- (READ-COMMITTED) コミット済みの読み取り:コミット済みのデータを読み取ることを許可し、ダーティリードを防ぐことができます。
- (REPEATABLE-READ) リピート可能読み取り:トランザクションが開始されると、トランザクション中に読み取ったすべてのデータは他のトランザクションによって変更されることは許可されず、ファントムリードを防ぐことはできません。
- (SERIALIZABLE) 直列化:最高レベルで、すべての問題を防ぎ、すべてのトランザクションが直列化された方法で順番に実行されます。
トランザクションの分離レベルの実装方法#
ロックと MVCC メカニズムに基づいて実装されます。
直列化分離レベルはロックを通じて実現され、他の分離レベルは MVCC に基づいて実現されます。
デフォルトの分離レベル#
SELECT @@transaction_isolation;
コマンドを実行して確認します。
デフォルトの分離レベルはリピート可能読み取りです。
MySQL ロック#
テーブルレベルロックと行レベルロック#
- テーブルレベルロック:ロック粒度が最も大きいロックで、非インデックスフィールドにロックをかけ、テーブル全体にロックをかけます。実装が簡単で、リソース消費が少なく、ロックが早く、デッドロックが発生しません。
- 行レベルロック:ロック粒度が最も小さいロックで、インデックスフィールドにロックをかけ、操作行にロックをかけます。ロックが遅く、デッドロックが発生する可能性があります。
行レベルロックの使用#
InnoDB は行レベルロックをインデックスフィールドに対して使用します。
update
やdelete
メソッドを実行する際、where
条件フィールドが一意のインデックスにヒットしない場合、またはインデックスが無効な場合、全テーブルをスキャンして全テーブルの行にロックをかけることになります。
一般的なロックの種類#
-
共有ロック(S ロック):別名読み取りロックで、トランザクションがデータを読み取る(select)際に共有ロックを取得し、複数のトランザクションが同時に取得することを許可します(ロック互換性があります)。
-
排他ロック(X ロック):別名書き込みロック、独占ロックで、トランザクションがレコードを変更する(update)際に排他ロックを取得し、複数のトランザクションが同時に取得することを許可しません。あるレコードに排他ロックがかかっている場合、他のトランザクションは他のタイプのロックをかけることができません(ロック互換性がありません)。
デフォルトではロックをかけず、明示的にロックを使用することを宣言できます。
SELECT ... LOCK IN SHARE MODE; # 共有ロック SELECT ... FOR UPDATE; # 排他ロック
-
意図ロック:テーブルレベルロックで、テーブル内に行ロックがあるかどうかを迅速に判断するために使用されます。
- 意図共有ロック:トランザクションがテーブル内のデータに共有ロックをかける意図がある場合、まず意図共有ロックをかける必要があります。
- 意図排他ロック:トランザクションがテーブル内のデータに排他ロックをかける意図がある場合、まず意図排他ロックをかける必要があります。
InnoDB におけるロック#
InnoDB には 3 種類の行ロックがあります:
- レコードロック(Record Lock):単一の行レコードに対するロック。
- ギャップロック(Gap Lock):範囲をロックし、レコード自体は含まれません。
- 次キーロック(Next-Key Lock):レコードロックとギャップロックを同時に使用します。
現在の読み取りとスナップショット読み取り#
InnoDB のデフォルトの分離レベル(リピート可能読み取り)はファントムリードの問題を解決できます。現在の読み取りとスナップショット読み取りを通じて。
- 現在の読み取り(一貫性ロック読み取り):ギャップロック(Next-Key Lock)を使用してロックをかけ、ファントムリードが発生しないようにします。
- スナップショット読み取り(一貫性非ロック読み取り):MVCC メカニズムによりファントムリードが発生しないことを保証します。
両者の違い
スナップショット読み取り:通常のselect
を使用する際、スナップショット読み取りが行われます。読み取ったデータがupdate/delete
操作を実行中の場合、読み取り操作はレコード上の排他ロックが解放されるのを待たずに、行の前のスナップショットを読み取ります。
現在の読み取り:トランザクションの分離レベルが RC(コミット済みの読み取り)および RR(リピート可能読み取り)の場合、InnoDB はロック読み取りを使用します。
- RC レベルでは:スナップショットデータに対して、現在の読み取りはロックされた行の最新のスナップショットデータを読み取ります。
- RR レベルでは:スナップショットデータに対して、現在の読み取りはトランザクション開始時の行データバージョンを読み取ります。
スナップショットはレコードの履歴バージョンであり、各行レコードには複数の履歴バージョンが存在する可能性があります。
MySQL パフォーマンス最適化#
ファイルストレージ#
MySQL でバイナリファイルデータを保存することは推奨されません。
オブジェクトストレージを使用してファイルを保存し、MySQL にはファイルのアドレスを保存することを推奨します。
IP アドレスの保存#
IP アドレスを整数型に変換して保存できます。
INET_ATON()
: IP を符号なし整数に変換します(4-8 ビット)INET_NTOA()
: 整数型の IP をアドレスに変換します。
可能な限り列を NOT NULL として定義する#
特別な理由がない限り NULL 値を使用するべきではなく、常にフィールドを NOT NULL に保つべきです。
- NULL 列のインデックスは追加のスペースを必要とするため、より多くのスペースを占有します;
- 比較や計算を行う際には NULL 値に特別な処理が必要です。
MySQL インデックス#
インデックスとは何か#
インデックスは、データを迅速に検索および取得するためのデータ構造であり、一般的なインデックス構造には:B ツリー、B + ツリー、ハッシュテーブルなどがあります。
インデックスのデータ構造#
ハッシュテーブル#
ハッシュテーブルはキーと値のペアの集合であり、キーを使用して迅速に値を得ることができます。O (1)。キーにハッシュアルゴリズムを適用してインデックスを計算し、そのインデックスを使用して値を見つけます。
欠点:
- ハッシュ衝突
- ハッシュインデックスは順序および範囲クエリをサポートしていません。
B ツリー#
B ツリーの詳細な説明や挿入削除操作などの関連内容は上文に詳しく説明されています。
私の B ツリーに対する理解:通常の二分木の欠点は、各ノードが 2 つの子ノードしか持てず、各ノードが 1 つのデータしか収容できないため、2 つの問題が発生します:1. 木の高さが非常に高い;2. 論理的に隣接するノードのデータが木の中で非常に遠くにあることがあり、メモリ内でデータを操作する場合には問題ではありません。
しかし、データベースでは、データはまずメモリ上ではなくディスク上に保存されます。過度に高い木は、複数回の検索が必要で、結果を取得し、比較し、再検索し、比較し、木の高さが高くなるほどディスクへのアクセス回数も増えます。ディスクにとってはあまり良い選択ではありません。「局所性の原理」を満たす場合、すなわち論理的に隣接するデータは物理的にできるだけ一緒に保存されるべきです。これにより、ディスクアクセス回数を減らすことができます。
B ツリーはこの問題を解決しました。B ツリーの特徴:1. 多路木であり、ノードが 2 つの子ノードしか持てないという制限がありません;2. すべての子ノードの高さが同じです。
B ツリーの各ノードはより多くのデータを収容できるため、木の高さが低くなり、論理的に隣接するデータが物理的に隣接したディスクスペースに保存されます。クエリ時にディスクの相互作用回数を減らします。
B ツリー:
上の図では、葉ノードに複数のデータがあり、検索時には葉ノード上のデータを一度にメモリに読み込み、メモリ内で走査して比較し、必要なデータを見つけます。
B ツリーの各ノードは 4K のデータを保存でき、ディスクストレージはデータをブロック単位で保存し、各ブロックのサイズは 4K です。データを読み取るたびに 1 つのノードを読み取り、4K のデータをメモリに読み込みます。
B + ツリー#
B + ツリーの子ノードはデータを保存せず、キーのインデックスのみを保存し、すべてのデータは葉ノードに保存されます。同時に、すべての葉ノードのデータは順序付きのリンクリストを構成します。
B + ツリーと B ツリーの比較#
- B + ツリーの検索速度はより安定しています。B + ツリーではすべてのデータが葉ノードに保存され、葉ノードの高さが同じであるため、各検索の回数が同じであり、検索速度が安定しています。
- B + ツリーの葉ノードは順序付きです。B + ツリーのすべての葉ノードのデータは順序付きのリンクリストを構成し、サイズ範囲のデータを検索する際により迅速です。
- B + ツリーの全ノードの走査はより迅速です。B + ツリーは葉ノードのみを走査する必要があり、B ツリーはすべてのノードを走査する必要があります。
- B ツリーでアクセスするデータが根ノードに近い場合、その時の検索速度は B + ツリーよりも速いです。
MyISAM と InnoDB のインデックス#
両者は B + ツリーをインデックス構造として使用しています。
-
MyISAM は非クラスタインデックスを使用:B + ツリーのノードのデータフィールドにデータのアドレスを保存し、検索時にはノードを見つけてからノード内のアドレスを使用してデータを見つけます。
-
InnoDB はクラスタインデックスを使用:B + ツリーのノードのデータフィールドに完全なデータを保存し、インデックスのキーはデータベースの主キーです。
インデックスの種類#
主キーインデックス#
データテーブルの主キー列は主キーインデックスを使用します。
テーブルに主キーが設定されていない場合、InnoDB はまずテーブル内に一意で NULL を許可しないフィールドがあるかどうかを確認し、あればそのフィールドを主キーとして使用し、なければ InnoDB は自動的に 6 バイトの自動増分主キーを作成します。
二次インデックス(補助インデックス)#
二次インデックスの葉ノードに保存されているデータは主キーであり、二次インデックスを使用して主キーを見つけることができます。
二次インデックスには一意インデックス、通常インデックス、プレフィックスインデックス、全文インデックスが含まれます。
- 一意インデックス(UNIQUE):データテーブルに一意のフィールドが設定され、重複を許可せず、NULL を許可します。
- 通常インデックス(INDEX):データテーブルに手動で設定されたインデックスフィールドで、重複を許可し、NULL を許可します。
- プレフィックスインデックス:文字列型データの最初の数文字を切り取ってインデックスを作成します。
- 全文インデックス(FULLTEXT):大きなテキストデータ内のキーワード情報を検索します。
クラスタインデックスと非クラスタインデックス#
クラスタインデックス#
クラスタインデックスはインデックス構造とデータが同時に保存されるインデックスです。主キーインデックスはクラスタインデックスです。特徴:検索が速く、更新が遅い。
- 利点:検索速度が速い。葉ノードにデータが保存され、データが順序付けられているため、葉ノードを見つけるとデータも見つかります。
- 欠点:
- 順序付けられたデータに依存:検索はデータの物理的なストレージアドレスがインデックスの順序に従って並んでいることに依存します。
- 更新コストが大きい:データの物理的なストレージアドレスがインデックスの順序に従って並んでいるため、挿入や削除のたびにデータを移動させ、物理的に順序を保つ必要があります。
非クラスタインデックス#
インデックス構造とデータが別々に保存されます。二次インデックスは非クラスタインデックスです。二次インデックスの葉ノードには主キーが保存されており、主キーを使用してデータを再度検索します。
- 利点:更新が速い。葉ノードにはデータが保存されていません。
- 欠点:
- 順序付けられたデータに依存。
- 再度の検索のためにテーブルを戻る必要がある場合があります。
カバリングインデックス#
カバリングインデックスは、クエリするフィールドがちょうどインデックスのフィールドである場合、そのインデックスに基づいて直接データを取得でき、テーブルを戻って検索する必要がありません。
複合インデックス#
テーブル内の複数のフィールドを使用してインデックスを作成します。
最左前方一致の原則#
複合インデックスを使用する場合、複合インデックス内のフィールドの順序に従って、左から右に順次クエリ条件内の複合インデックス内の最左フィールドと一致するフィールドを照合します。
インデックスフィールド作成の原則#
- 頻繁にクエリされ、クエリ条件や結合クエリに使用されるフィールド
- NULL でないフィールド
- 頻繁にソートされるフィールド
- 頻繁に更新されないフィールド
- 可能な限り単一列インデックスではなく複合インデックスを使用する
MySQL ログ#
MySQL ログは主にバイナリログ(binlog、アーカイブログ)、トランザクションログ(redo log)、ロールバックログ(undo log)で構成されています。
redo log#
Redo log は InnoDB が使用するログシステムであり、各データページで行われた変更を記録します。redo log を使用してエラーからデータを回復できます。データの永続性と完全性を保証します。MySQL サービスが異常停止した場合、MySQL を再起動すると、redo log を通じてデータが回復されます。
MySQL データクエリ時、ディスクからデータをページ単位で読み取り、クエリ時には一度に 1 ページのデータ(16kb)をBuffer Pool
にロードします。以降のクエリはBuffer Pool
内で優先的に検索されます。更新操作を実行する際も、Buffer Pool
内のデータを更新し、同時にリドゥログバッファ(redo log buffer)にリドゥログを記録し、その後適切なタイミングでバッファをディスクのリドゥログファイルにフラッシュします。
フラッシュのタイミング#
フラッシュ:データをメモリからディスクに書き込むこと
innodb_flush_log_at_trx_commit
パラメータを使用してフラッシュのタイミングを制御できます:- 0:各トランザクションコミット時にフラッシュ操作を行わない(データ損失のリスク)
- 1:各トランザクションコミット時にフラッシュを行う(デフォルト値)(未コミットのトランザクションのデータ損失はない)
- 2:各トランザクションコミット時に
redo log buffer
の内容をシステムキャッシュpage cache
に書き込みます。
デフォルトでは、トランザクションがコミットされるたびにfsync
を呼び出してリドゥログをフラッシュします。
- 同時に、InnoDB は 1 秒ごとに自動的に
redo log buffer
の内容をシステムキャッシュpage cache
に書き込み、その後fsync
でフラッシュします。 redo log buffer
がinnodb_log_buffer_size
の半分を超えると、フラッシュがトリガーされます。
ログファイルグループ#
複数のファイルが redo log ログを保存し、1 つのファイルが満杯になると次のファイルに書き込み、最後のファイルが満杯になると最初のファイルに戻って書き込みます。
binlog#
binlog はデータベース操作のロジックを記録し、各データテーブルの更新を記録します。
MySQL の主従同期時には、binlog を使用してデータを同期します。
記録形式#
binlog_format
パラメータを使用して記録形式を指定します。
- statement:SQL 文の原文を記録しますが、
update_time=now()
を実行すると時間が異なる可能性があります。 - row:実行された SQL のパラメータを記録し、具体的な時間を記録します。
- mixed:この SQL がデータ不一致の問題を引き起こすかどうかを自動的に判断し、問題がある場合は row を使用し、問題がない場合は statement を記録します。
書き込みメカニズム#
トランザクション実行中に、まずログをbinlog cache
に書き込み、トランザクションがコミットされた後にbinlog cache
を binlog に書き込みます。
二段階コミット#
redo log と binlog が相互に連携してデータ回復能力とデータ損失を防ぐことを最大限に保証します。
ログ記録の順序。
更新操作を実行する際、まず redo log に書き込み、状態を prepare に設定し、トランザクションがコミットされた後に更新操作を binlog に書き込み、redo log の状態を commit 段階に設定します。
もし redo log の状態が prepare 段階の時に MySQL サービスが異常になった場合、データを回復する際にトランザクションがコミットされていないため、binlog がなく、MySQL はこのトランザクションをロールバックすることを選択します。
もしトランザクションがコミットされ、binlog がある場合、MySQL は binlog を通じてデータを回復し、redo log の状態を commit 段階に設定します。
undo log#
undo log はトランザクションの原子性を保証し、トランザクション異常時に操作をロールバックするために使用されます。
すべてのトランザクション操作は、実際の操作を実行する前にロールバックログを記録します。同時に、ロールバックログはデータがディスクに永続化される前に記録されます。
3 つのログの役割#
- redo log を使用してトランザクションの永続性を保証します。
- undo log を使用してトランザクションの原子性を保証します。
- redo log と undo log を使用してデータの損失を防ぎます。
- binlog を使用して完全なデータバックアップ、主従、データの一貫性を保証します。
MVCC#
MVCC#
Multi-Version Concurrency Control(多バージョン同時実行制御)。データベース管理システムにおいて、データベースへの同時アクセスを実現するための並行制御の方法です。
実装原理#
隠しフィールド#
- DB_ROW_ID:隠し自動増分主キー。データテーブルに主キーがない場合、InnoDB は自動的に DB_ROW_ID などのフィールドを使用してクラスタインデックスを生成します。
- DB_TRX_ID:最近挿入 / 変更されたトランザクション ID。現在のレコードを最後に変更したトランザクション ID を記録します。
- DB_ROLL_PTR:ロールバックポインタ。レコードの前のバージョンを指します。
- DRFAULT_BIT:削除フラグ。
undo log#
ReadView#
トランザクションがスナップショット操作を行う際に生成される読み取りビュー。このトランザクションがスナップショットを実行する際に、データベースシステムの現在のスナップショットが生成され、現在のアクティブなトランザクションの ID が記録され、維持されます。
ReadView の 3 つの属性
- trx_list:未コミットのトランザクション ID リスト
- up_limit_id:trx_list リスト内の最小のトランザクション ID を記録します。
- low_limit_id:次のトランザクション ID、すなわち現在の最大 ID + 1 です。
SQL 実行フロー#
- コネクタ:データベース接続、認証、権限検証
- アナライザー:字句解析(キーワードの抽出、select、テーブル名、クエリ条件など)、構文解析(SQL が MySQL の規範に従っているかどうかを確認)
- オプティマイザー:(IO コスト + CPU コスト)が最小のインデックスを使用してクエリを実行
- 実行者:ストレージエンジンインターフェースを呼び出して SQL を実行
- BufferPool 内に必要なクエリデータがあるかどうかを確認し、ない場合はディスクを検索し、その後データを BufferPool に配置します。
- 更新を実行する場合、undo log を記録し、BufferPool 内のデータを更新します。(BufferPool 内のデータはデータベース内のデータと一致しない可能性があります)
- BufferPool 内のデータが更新され、redo log を記録します(まず redo log buffer に書き込み、その後適切なタイミングでディスクに書き込みます)。
- bin log を記録します。
- bin log ファイル名と現在の文の更新内容を redo log に記録します。
- redo log の後に commit を追加します(二段階コミット)。
インデックスの無効化#
演算子( = )の左右のデータ型が異なる場合、暗黙の変換が発生します。
無効化の状況#
- where の左側が数値型の場合、暗黙の変換が発生し、インデックスは無効にならず、効率への影響は大きくありません。
- where の左側が文字列型の場合、暗黙の変換が発生し、インデックスは無効になり、クエリが全テーブルスキャンに変わり、効率が低下します。
文字列 => 数値変換方式:#
- 数字で始まらないすべての文字列は 0 に変換されます。(例えば
abc
、abc123 =>0
) - 数字で始まる文字列は最初の数字のみを切り取ります。(例えば
123abc4
=> 123、012ab4
=> 12)
無効化のケース#
インデックス無効化のケース:num2 はvarchar
型です。
SELECT * FROM `test1` WHERE num2 = 10000;
この SQL を実行するとインデックスが無効になり、全テーブルスキャンが発生します。なぜなら'10000a'
、'010000'
、'10000'
などはすべて浮動小数点数10000
に変換できるため、このような場合はインデックスを使用できません。
インデックスの無効化#
- 上述の例では、型変換が原因でインデックスが無効になりました。
- != > < を使用するとインデックスが無効になります。
- あいまいなクエリ(例:% S%)はインデックスを無効にしますが、S% はインデックスを無効にしません。
MySQL における文の実行優先順位#
単一テーブル#
from > where > group by > select > order by > limit
複数テーブル#
from > join > on > where > group by > AVG,SUM > having > select > distinct > order by > limit
スロークエリの最適化#
EXPLAIN キーワードを使用してクエリ文を分析します。
クエリでインデックスを使用する#
- LIKE あいまい検索を使用する場合、最初が % の場合はインデックスが使用されません。
データベース構造の最適化#
フィールドが多いテーブルを分割し、あまりクエリされないデータを新しいテーブルに作成します。