MySQL のインデックスの原理とクエリの最適化の詳細な説明

MySQL のインデックスの原理とクエリの最適化の詳細な説明

1. はじめに

1. インデックスとは何ですか?

一般的なアプリケーション システムでは、読み取りと書き込みの比率は約 10:1 であり、挿入操作や一般的な更新操作でパフォーマンス上の問題が発生することはほとんどありません。実稼働環境では、最も一般的で最も問題となる操作は依然として複雑なクエリ操作であるため、クエリ ステートメントの最適化が最優先事項であることは明らかです。クエリの高速化に関しては、インデックスについて言及する必要があります。

2. インデックスはなぜ必要なのでしょうか?

インデックスは、MySQL では「キー」とも呼ばれ、ストレージ エンジンがレコードをすばやく検索するために使用するデータ構造です。インデックスはパフォーマンス向上に重要

特にテーブル内のデータ量が増加すると、インデックスがパフォーマンスに与える影響はますます重要になります。

インデックスの最適化は、クエリのパフォーマンスを最適化するための最も効果的な手段です。インデックスを使用すると、クエリのパフォーマンスを簡単に数桁向上できます。

索引は辞書の発音表に相当します。ある単語を調べたい場合、発音表を使わないと何百ページもの辞書を一つ一つ調べる必要があります。

2. インデックスの原則

1つのインデックス原則

インデックスの目的はクエリの効率を向上させることです。これは、書籍の検索に使用するカタログと同じです。まず章を見つけ、次に章の下のサブセクションを見つけ、最後にページ番号を見つけます。同様の例としては、辞書を調べる、電車のスケジュールやフライトスケジュールを確認するなどが挙げられます。

本質は、取得するデータの範囲を継続的に絞り込むことで最終的な目的の結果をフィルタリングし、同時にランダムなイベントを連続したイベントに変換することです。言い換えれば、このインデックスメカニズムを使用すると、常に同じ検索方法を使用してデータをロックできます。

データベースでも同じことが言えますが、等価クエリだけでなく、範囲クエリ(>、<、between、in) 、あいまいクエリ (like)、結合クエリ (or) なども発生するため、明らかにはるかに複雑です。データベースは、すべての問題に対処するためにどのように選択すればよいでしょうか?辞書の例をもう一度考えてみましょう。データをセグメントに分割し、セグメントごとにクエリを実行することはできますか?最も簡単な方法は、1,000 個のデータを 1 から 100 までの数字を含む最初のセクション、101 から 200 までの数字を含む 2 番目のセクション、201 から 300 までの数字を含む 3 番目のセクションに分割することです。次に、250 番目のデータを確認するには、3 番目のセクションを見つけるだけでよいため、無効なデータの 90% を一度に排除できます。しかし、レコードが 1,000 万件ある場合は、いくつのセグメントに分割すればよいのでしょうか?アルゴリズムの基礎知識を持つ学生は、平均複雑度が lgN でクエリ パフォーマンスが優れている検索ツリーについて考えるでしょう。しかし、ここで重要な問題を見落としています。複雑性モデルは、毎回同じ操作のコストに基づいています。データベースの実装は比較的複雑です。一方では、データはディスクに保存されます。他方では、パフォーマンスを向上させるために、データの一部を毎回計算のためにメモリに読み込むことができます。ディスクへのアクセスのコストはメモリへのアクセスの約 10 万倍であることがわかっているため、単純な検索ツリーでは複雑なアプリケーション シナリオに対応することが困難です。

2. ディスクIOと事前読み取り

ディスク IO は非常にコストのかかる操作であることを考慮して、コンピューターのオペレーティング システムではいくつかの最適化が行われています。IO中は、現在のディスク アドレスのデータだけでなく、隣接するデータもメモリ バッファーに読み込まれます。これは、ローカル事前読み取りの原理により、コンピューターがアドレスのデータにアクセスすると、そのアドレスに隣接するデータにもすばやくアクセスされるためです。 IO によって毎回読み取られるデータはページと呼ばれます。ページの具体的なサイズはオペレーティング システムによって異なりますが、通常は 4k または 8k です。つまり、ページ内のデータを読み取る場合、実際に発生する IO は 1 つだけです。この理論は、インデックス データ構造の設計に非常に役立ちます。

3. インデックスデータ構造

データ構造はどこからともなく生まれるものではありません。データ構造には、必ず背景と使用シナリオがあります。このデータ構造に何が必要なのかをまとめてみましょう。実際、それは非常に単純です。つまり、データを検索するたびに、ディスク IO 回数を非常に小さな桁、できれば一定の桁に制御するのです。では、高度に制御可能な多方向検索ツリーがニーズを満たすことができるかどうか疑問に思います。このようにして、b+ツリーが誕生しました。

上の図に示すように、これは b+ ツリーです。b+ ツリーの定義については、B+ ツリーを参照してください。ここでは、いくつかの重要な点についてのみ説明します。水色のブロックはディスク ブロックと呼ばれます。各ディスク ブロックには、いくつかのデータ項目 (濃い青で表示) とポインター (黄色で表示) が含まれていることがわかります。たとえば、ディスク ブロック 1 にはデータ項目 17 と 35 が含まれており、ポインター P1、P2、および P3 が含まれています。P1 は 17 未満のディスク ブロックを表し、P2 は 17 から 35 の間のディスク ブロックを表し、P3 は 35 より大きいディスク ブロックを表します。実際のデータは、リーフ ノード 3、5、9、10、13、15、28、29、36、60、75、79、90、および 99 に存在します。非リーフ ノードには実際のデータは保存されず、検索方向を指示するデータ項目のみ保存されます。たとえば、17 と 35 は実際にはデータ テーブルに存在しません。

###b+ ツリー検索プロセス

図に示すように、データ項目 29 を検索する場合、最初にディスク ブロック 1 がディスクからメモリにロードされます。このとき、IO が発生します。メモリ内でバイナリ検索を使用して、29 が 17 と 35 の間にあることを判別します。ディスク ブロック 1 の P2 ポインターはロックされています。メモリ時間は非常に短いため (ディスク IO と比較して) 無視できます。ディスク ブロック 3 は、ディスク ブロック 1 の P2 ポインターのディスク アドレスを介してディスクからメモリにロードされます。2 番目の IO が発生します。29 は 26 と 30 の間にあります。ディスク ブロック 3 の P2 ポインターはロックされています。ディスク ブロック 8 は、ポインターを介してメモリにロードされます。3 番目の IO が発生します。同時に、メモリ内でバイナリ検索を実行して 29 を見つけ、クエリが終了します。合計 3 つの IO が実行されます。実際には、3 層の B+ ツリーは数百万のデータを表すことができます。数百万のデータの検索に 3 つの IO しか必要ない場合、パフォーマンスは大幅に向上します。インデックスがない場合、各データ項目に IO が必要になり、合計で数百万の IO が必要になりますが、これは明らかに非常にコストがかかります。

###b+ツリープロパティ

1. インデックスフィールドはできるだけ小さくする必要があります。上記の分析により、IO回数はb+numberの高さhに依存することがわかります。現在のデータテーブルのデータがNで、各ディスクブロックのデータ項目数がmであると仮定すると、h=㏒(m+1)Nとなります。データ量Nが一定の場合、mが大きいほどhは小さくなります。m = ディスクブロックサイズ/データ項目サイズです。ディスクブロックサイズはデータページのサイズで、固定されています。データ項目が占めるスペースが小さく、データ項目の数が多い場合、ツリーの高さは低くなります。このため、各データ項目、つまりインデックス フィールドは、できるだけ小さくする必要があります。たとえば、int は 4 バイトを占めますが、これは bigint の 8 バイトの半分です。このため、b+ ツリーでは、実際のデータを内部ノードではなくリーフ ノードに配置する必要があります。内部ノードに配置すると、ディスク ブロックのデータ項目が大幅に減少し、ツリーの高さが増加します。データ項目が 1 に等しい場合、線形リストに退化します。

2. インデックスの左端のマッチング機能(つまり、左から右へのマッチング) :b+ツリーのデータ項目が(名前、年齢、性別)などの複合データ構造である場合、b+ツリーは左から右の順に検索ツリーを構築します。たとえば、(張三、20、F)などのデータが取得されると、b+ツリーは最初に名前を比較して次の検索方向を決定します。名前が同じ場合は、年齢と性別が順番に比較され、最終的に取得されたデータを取得します。ただし、(20、F)などの名前のないデータが来ると、b+ツリーは次にどのノードをチェックすればよいかわかりません。これは、名前が検索ツリーを構築するときの最初の比較要素であり、次にどこを照会するかを知るために最初に名前に基づいて検索する必要があるためです。たとえば、(Zhang San, F) のようなデータを取得する場合、b+ ツリーは名前を使用して検索方向を指定できますが、次のフィールド age が欠落しているため、名前が Zhang San と同じデータのみを検索し、その後、性別が F のデータと一致させます。これは非常に重要なプロパティであり、インデックスの最も左の一致機能です。

4.MySQLインデックス管理

1. 機能

#1. インデックスの機能は検索を高速化することです

#2. MySQL の主キー、一意キー、および結合一意キーもインデックスです。検索を高速化するだけでなく、これらのインデックスには制約もあります。

2. MySQLインデックスの分類

インデックスの分類 1. 通常のインデックス インデックス: 検索を高速化 2. ユニークインデックス 主キー インデックス: 主キー: 検索を高速化 + 制約 (空ではなくユニーク)
    ユニークインデックス: ユニーク: 検索を高速化 + 制約 (ユニーク)
3. 複合インデックス -主キー(id,name): 複合主キーインデックス -ユニーク(id,name): 複合ユニークインデックス -インデックス(id,name): 複合通常インデックス 4. 全文インデックス fulltext: 非常に長い記事を検索する場合に最も効果的です。
5. 空間インデックス: 理解するだけで、ほとんど使用されない
1 たとえば、ショッピングモールの会員カードシステムを作成するとします。
 2 
 3 このシステムには、次のフィールドを持つメンバー テーブル 4 があります。
 5 会員番号 INT
 6 メンバー名 VARCHAR(10)
 7 会員ID番号 VARCHAR(18)
 8 メンバーの電話番号 VARCHAR(10)
 9 メンバーの住所 VARCHAR(50)
10 メンバーの発言 本文
11 
12 次に、この会員番号を主キーとして使用し、PRIMARY
13 メンバー名のインデックスを作成する場合は、通常のINDEXを使用します。
14 会員ID番号のインデックスを作成する場合は、UNIQUE(一意、重複不可)を選択できます。
15 
16 #さらに、フルテキストインデックス、つまりFULLTEXTがあります
17 メンバーメモ情報。インデックスを作成する必要がある場合は、全文検索を選択できます。
18 は非常に長い記事を検索する場合に最適です。
19 は短いテキストに使用されます。1 行または 2 行だけの場合は、通常の INDEX でも機能します。
20 しかし、実際には、全文検索には MySQL に付属のインデックスを使用せず、全文検索専用の Sphinx などのサードパーティ製ソフトウェアを選択します。
21 
22 #空間インデックスSPATIALなどの他のインデックスについては、理解するだけで、各インデックスが使用されないアプリケーションシナリオはほとんどありません。

3. 2つの主要なインデックスの種類: ハッシュとBツリー

#上記のインデックスを作成するときに、インデックスの種類を指定できます。ハッシュ タイプのインデックスには、高速な単一クエリと低速な範囲クエリの 2 種類があります。Btree タイプのインデックス: B+ ツリー、レイヤーが増えるほど、データ量が指数関数的に増加します (InnoDB がデフォルトでサポートしているため、これを使用します)
#異なるストレージ エンジンは異なるインデックス タイプをサポートします。InnoDB はトランザクション、行レベルのロック、B ツリー、フルテキストなどのインデックスをサポートしますが、ハッシュ インデックスはサポートしません。
MyISAM はトランザクションをサポートしていませんが、テーブル レベルのロック、B ツリー、フルテキスト、およびその他のインデックスをサポートしていますが、ハッシュ インデックスはサポートしていません。
メモリはトランザクションをサポートしていませんが、テーブル レベルのロック、B ツリー、ハッシュ、およびその他のインデックスをサポートしていますが、フルテキスト インデックスはサポートしていません。
NDB はトランザクション、行レベルのロック、ハッシュ インデックスをサポートしますが、B ツリー、フルテキスト、その他のインデックスはサポートしません。
アーカイブはトランザクションをサポートしていませんが、テーブル レベルのロックはサポートしています。B ツリー、ハッシュ、フルテキスト、およびその他のインデックスはサポートしていません。

4. インデックスの作成/削除の構文

1 #方法1:テーブルを作成する場合 2 CREATE TABLE テーブル名 (
 3 フィールド名 1 データ型 [整合性制約…]、
 4 フィールド名 2 データ型 [整合性制約…]、
 5 [ユニーク | フルテキスト | 空間] インデックス | キー
 6 [インデックス名] (フィールド名 [(長さ)] [ASC | DESC]) 
 7 );
 8 
 9 
10 #方法 2: CREATE は既存のテーブルにインデックスを作成します 11 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX インデックス名 12 ON テーブル名 (フィールド名 [(長さ)] [ASC | DESC]);
13 
14 
15 #方法3: ALTER TABLE 既存のテーブルにインデックスを作成する 16 ALTER TABLE テーブル名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
17 インデックス名 (フィールド名 [(長さ)] [ASC | DESC]);
18                              
19 #インデックスの削除: DROP INDEX インデックス名 ON テーブル名;
インデックスの作成/削除の構文

インデックスの作成/削除の構文

ヘルプドキュメントを活用して作成する
インデックスの作成を支援
==================
1. インデックスを作成する - テーブルを作成するときに作成します(注意すべき点がいくつかあります)
    テーブルs1を作成します(
    id int、#ここに主キーを追加できます
    #id int index #index は単なるインデックスであり、制約ではないため、このようにインデックスを追加することはできません。
    #主キーや一意制約などのフィールドを定義するときに、インデックス名 char(20) を追加することはできません。
    年齢 int、
    メールアドレスvarchar(30)
    #主キー(id) #インデックス(id) を追加することもできます #次のように追加できます);
    - テーブルを作成した後、create index name on s1(name); #共通インデックスを追加しますcreate unique age on s1(age);一意のインデックスを追加しますalter table s1 add primary key(id); #住宅および建設インデックスを追加します。つまり、id フィールドに主キー制約を追加しますcreate index name on s1(id,name); #共通の結合インデックスを追加します2. インデックスを削除しますdrop index id on s1;
    drop index name on s1; #共通インデックスを削除しますdrop index age on s1; #ユニークインデックスを削除します。共通インデックスと同様に、削除するためにインデックスの前に unique を追加する必要はなく、直接削除できますalter table s1 drop primary key; #プライマリキーを削除します (alter に従って追加されたため、削除にも alter を使用します)

ヘルプビュー

5. テストインデックス

1. 準備

#1. テーブルを準備する create table s1(
id int、
名前varchar(20),
性別文字(6)
メールアドレスvarchar(50)
);
#2. バッチでレコードを挿入するストアドプロシージャを作成します。区切り文字は $$ です。#ストアドプロシージャの終了記号を $$ と宣言します。
プロシージャ auto_insert1() を作成する
始める
    i int をデフォルトで 1 と宣言します。
    i<3000000の場合
        s1 に値 (i、concat ('egon'、i)、'male'、concat ('egon'、i、'@oldboy')) を挿入します。
        i=i+1 と設定します。
    終了しながら;
END$$ #$$区切り記号の終了; #セミコロンを終了記号として再宣言します#3. ストアド プロシージャを表示します show create procedure auto_insert1\G 
#4. ストアド プロシージャ call auto_insert1(); を呼び出します。

2. インデックスなしでクエリ速度をテストする

#インデックスなし: 最初から最後までスキャンするため、クエリ速度が非常に遅くなります。mysql> select * from s1 where id=333;
+------+---------+--------+----------------+
| ID | 名前 | 性別 | メール |
+------+---------+--------+----------------+
| 333 | egon333 | 男性 | [email protected] |
| 333 | egon333 | f | alex333@oldboy |
| 333 | egon333 | f | alex333@oldboy |
+------+---------+--------+----------------+
セット内の行数 (0.32 秒)
mysql> s1 から * を選択します。ここで、email は 'egon333@oldboy' です。
....
... 行セット (0.36 秒)

3. インデックスを追加する

#1. 検索条件フィールドのインデックスを必ず作成してください。たとえば、select * from t1 where age > 5; の場合は、age のインデックスを追加する必要があります。#2. テーブルにすでに大量のデータがある場合、インデックスの作成には非常に時間がかかり、ハードディスクの容量を消費します。挿入、削除、更新はすべて非常に遅くなります。クエリだけが高速です。たとえば、create index idx on s1(id); はテーブル内のすべてのデータをスキャンし、id をデータ項目として使用してインデックス構造を作成し、ハードディスク上のテーブルに格納します。
作成後、クエリは非常に高速になります #3。innodbテーブルのインデックスはs1.ibdファイルに保存されますが、myisamテーブルのインデックスには別のインデックスファイルtable1.MYIがあることに注意してください。

6. インデックスを正しく使用する

1. カバーインデックス

#分析 select * from s1 where id=123;
SQL はインデックスにヒットしますが、それをカバーしません。
id=123 を使用して、ハードディスク内、またはインデックス データ構造内のデータ テーブル内の ID の場所を特定します。
ただし、選択したフィールドは * であり、id 以外のフィールドも必要なので、インデックス構造を通じて id を取得するだけでは不十分です。
また、IDを使用して、IDが配置されている行の他のフィールド値を見つける必要があり、時間がかかります。明らかに、IDのみを選択した場合、
この問題は次のようにすると解消されます: select id from s1 where id=123;
これはカバーリングインデックスです。インデックスをヒットし、インデックスデータ構造からハードディスク上のIDのアドレスを直接取得します。速度が非常に速いです。

2. 共同インデックス

3. インデックスの結合

#インデックスのマージ: 複数の単一列インデックスをマージし、#分析を使用します。
インデックスのマージを使用すると、結合インデックスで実行できるすべての問題を解決できます。たとえば、create index ne on s1(name,email);#Combined index のように、name と email のインデックスを個別に作成できます。結合インデックスでは、次の操作を実行できます。
name='egon' の場合、s1 から * を選択します。
name='egon' かつ email='adf' の場合、s1 から * を選択します。
インデックスのマージにより次のことが起こります:
name='egon' の場合、s1 から * を選択します。
email='adf' の場合、s1 から * を選択します。
name='egon' かつ email='adf' の場合、s1 から * を選択します。
一見すると、インデックスのマージのほうが優れているように見えます。より多くのケースにヒットしますが、実際にはケースによって異なります。name='egon'、email='adf'の場合、
その場合、結合インデックスの効率はインデックスマージの効率よりも高くなります。単一条件クエリの場合は、インデックスマージを使用する方が合理的です。

インデックスを使用してクエリ速度を向上させるという望ましい効果を得るには、インデックスを追加するときに次の原則に従う必要があります。

#1. 左端のプレフィックス一致の原則は非常に重要な原則です。
s1(name,email,) にインデックス ix_name_email を作成します。
- 左端のプレフィックス一致: 左から右に一致する必要があります。 select * from s1 where name='egon'; #ok select * from s1 where name='egon' and email='asdf'; #ok select * from s1 where email='[email protected]'; #No MySQL は、範囲クエリ (>、<、between、like) に遭遇して一致を停止するまで、右側への一致を続けます。
例えば、a = 1、b = 2、c > 3、d = 4の場合、(a、b、c、d)の順序でインデックスを作成すると、
d のインデックスは必要ありません。(a,b,d,c) のインデックスを作成すれば、すべて使用できます。a,b,d の順序は任意に調整できます。
#2.= および in は任意の順序で指定できます。たとえば、a = 1、b = 2、c = 3 です。(a、b、c) インデックスは任意の順序で作成できます。MySQL クエリ オプティマイザーは、インデックスが認識できる形式に最適化するのに役立ちます。#3. インデックスとして識別性の高い列を選択するようにしてください。識別の式は count(distinct col)/count(*) です。
重複しないフィールドの割合を示します。割合が大きいほど、スキャンするレコードが少なくなります。一意のキーの識別は1ですが、一部の州では、
ビッグデータでは性別フィールドの識別値は 0 になる可能性があるため、この比率に経験的な価値があるのか​​と疑問に思う人もいるかもしれません。さまざまな使用シナリオ、
この値も決定するのが困難です。一般的に、結合する必要があるフィールドは 0.1 以上である必要があります。つまり、1 つのレコードに対して平均 10 レコードがスキャンされます。#4. インデックス列は計算に使用できません。列は「クリーン」な状態にしておいてください (from_unixtime(create_time) = '2014-05-29' など)。
インデックスは使用できません。理由は非常に簡単です。B+ツリーはフィールド値をデータテーブルに格納します。
ただし、検索時には、比較のためにすべての要素に関数を適用する必要があり、コストがかかりすぎるのは明らかです。
したがって、ステートメントは create_time = unix_timestamp('2014-05-29'); と記述する必要があります。

左端の接頭辞のデモンストレーション

mysql> s1 から * を選択します。ここで、id>3 かつ name='egon' かつ email='[email protected]' かつ gender='male' です。
空集合(0.39秒)
mysql> create index idx on s1(id,name,email,gender); # 左端のプレフィックスがフォローされていません クエリは正常、0 行が影響を受けました (15.27 秒)
レコード: 0 重複: 0 警告: 0
mysql> s1 から * を選択します。ここで、id>3 かつ name='egon' かつ email='[email protected]' かつ gender='male' です。
空セット(0.43秒)

mysql> s1 のインデックス idx を削除します。
クエリは正常、影響を受けた行は 0 行 (0.16 秒)
レコード: 0 重複: 0 警告: 0
mysql> create index idx on s1(name,email,gender,id); # 左端のプレフィックスに従います クエリは正常です。0 行が影響を受けました (15.97 秒)
レコード: 0 重複: 0 警告: 0
mysql> s1 から * を選択します。ここで、id>3 かつ name='egon' かつ email='[email protected]' かつ gender='male' です。
空セット (0.03 秒)
1 6. 左端のプレフィックスは 2 index(id,age,email,name) に一致します
 3 #id は条件内に出現する必要があります (id が出現する限り、速度が向上します)
 4 id
 5 id 年齢
 6 ID メール
 7 ID名
 8 
 9 email #いいえ、これが最初であれば、速度は向上しません。 10 mysql> select count(*) from s1 where id=3000;
11 +---------+
12 | カウント(*) |
13 +---------+
14 | 1 |
15 +----------+
16 セット内 1 列 (0.11 秒)
17 
18 mysql> s1(id,name,age,email); にインデックス xxx を作成します。
19 クエリは正常、影響を受けた行は 0 行 (6.44 秒)
20 レコード: 0 重複: 0 警告: 0
21 
22 mysql> s1からcount(*)を選択します。id=3000;
23 +---------+
24 | カウント(*) |
25 +---------+
26 | 1 |
27 +----------+
28 セット内 1 行 (0.00 秒)
29 
30 mysql> name='egon' で s1 から count(*) を選択します。
31 +---------+
32 | カウント(*) |
33 +---------+
34 | 299999 |
35 +---------+
36 セット内 1 列 (0.16 秒)
37 
38 mysql> s1 から count(*) を選択します。email='[email protected]';
39 +---------+
40 | カウント(*) |
41 +---------+
42 | 1 |
43 +---------+
44 セット内 1 列 (0.15 秒)
45 
46 mysql> id=1000、email='[email protected]' の場合、s1 から count(*) を選択します。
47 +----------+
48 | カウント(*) |
49 +---------+
50 | 0 |
51 +----------+
52 セット内 1 行 (0.00 秒)
53 
54 mysql> email='[email protected]' かつ id=3000 の場合、s1 から count(*) を選択します。
55 +---------+
56 | カウント(*) |
57 +---------+
58 | 0 |
59 +----------+
60 セット内 1 行 (0.00 秒)
左端の一致のジョイントインデックスを作成する

インデックスにヒットしない場合は、次の点に注意してください。

- '%xx' のように
    tb1 から * を選択します。メールアドレスは '%cn' のようなものになります。
    
- 関数 select * from tb1 where river(email) = 'wupeiqi'; を使用します。
    
- または
    nid = 1 または name = '[email protected]' の場合、tb1 から * を選択します。
    
    特殊: or 条件にインデックスが付けられていない列がある場合にのみ無効になります。次の例では、インデックス select * from tb1 where nid = 1 or name = 'seven' を使用します。
            nid = 1 または name = '[email protected]' かつ email = 'alex' の場合、tb1 から * を選択します。
            
- 型の不一致 列が文字列型の場合、入力条件は引用符で囲む必要があります。それ以外の場合は...
    tb1 から * を選択します (email = 999)。
通常のインデックスは、インデックスが使用されないことを意味するものではありません - !=
    tb1 から * を選択します。メールアドレスが != 'alex' の場合
    特別: 主キーの場合、インデックスは引き続き使用されます。select * from tb1 where nid != 123
->
    tb1 から * を選択し、メール > 'alex' を選択します。
    
    特別: 主キーまたはインデックスが整数型の場合、インデックスは引き続き使用されます。select * from tb1 where nid > 123
        tb1 から * を選択 (num > 123)
        
#ソート条件がインデックスの場合、選択フィールドもインデックスフィールドである必要があります。そうでない場合はヒットしません - order by
    s1 から名前を選択、電子メールで順序を指定、desc;
    インデックスで並べ替える場合、選択したクエリ フィールドがインデックスでない場合、インデックスは使用されません。select email from s1 order by email desc;
    特別: 主キーがソートされている場合でも、インデックスは使用されます。
        tb1 から * を選択し、nid desc で並べ替えます。
- 結合インデックスの左端のプレフィックス 結合インデックスが次の場合: (名前、メール)
    名前とメール - インデックスを使用 名前 - インデックスを使用 メール - インデックスを使用しないでください - count(1) または count(column) の代わりに count(*) を使用しても、mysql では違いはありません - tb(title(19)) にインデックス xxxx を作成します #テキスト タイプ、長さを指定する必要があります
- select *の使用を避ける
- count(*) の代わりに count(1) または count(column)
- テーブルを作成するときは、varcharではなくcharを使用するようにしてください。
- テーブル内のフィールドの順序は固定長フィールドが最初です - 複数の単一列インデックスの代わりに複合インデックスを使用します(クエリに複数の条件が頻繁に使用される場合)
- 可能な限り短いインデックスを使用する - サブクエリの代わりにJOINを使用する
- テーブルを結合するときは、条件タイプが一貫していることを確認してください - インデックスハッシュ値(重複が少ない)はインデックス作成に適していません。例:性別は適していません

7. 低速クエリの最適化の基本手順

0. 最初に実行して本当に遅いかどうかを確認し、SQL_NO_CACHEを設定します
1. Where条件の単一テーブルクエリで、最小の戻りレコードテーブルをロックします。この文は、返されるレコード数が最も少ないテーブルにクエリ ステートメントの where 句を適用し、クエリを開始することを意味します。テーブルの各フィールドを個別にクエリして、どのフィールドの識別度が最も高いかを確認します。2. 実行プランが 1 の期待と一致しているかどうかを確認することを説明します (ロックされたレコードが少ないテーブルからクエリを開始します)。
3. order by limit 形式の SQL 文を使用して、ソートされたテーブルに優先順位を付けます。4. ビジネス側の使用シナリオを理解します。5. インデックスを追加するときは、インデックス作成の主要な原則を参照してください。6. 結果を観察します。期待どおりでない場合は、0 から分析を続けます。

要約する

この記事はこれで終わりです。皆さんのお役に立てれば幸いです。また、123WORDPRESS.COM のその他のコンテンツにも注目していただければ幸いです。

以下もご興味があるかもしれません:
  • MySQLクエリ最適化のための実用的な方法のまとめ
  • SQL Server クエリ ステートメント ブロックの最適化パフォーマンス
  • MySQL の遅いクエリの最適化ソリューション
  • MySQL 大規模データクエリの最適化アイデアの詳細な分析
  • 20秒でSQLの遅いクエリを最適化するソリューション
  • MySQL で遅いクエリ SQL を見つけて最適化する詳細な例
  • SQLは複合インデックスを使用してデータベースクエリを最適化します

<<:  CSS3は三角形の連続拡大効果を実現します

>>:  ウェブサイトをより高く、よりデザイン的に見せる方法

推薦する

Centos8 で Apache httpd2.4.37 を使用して Web サーバーをインストールする詳細な手順

ステップ 1: yum install httpd -y #httpd サービスをインストールします...

主要ブラウザとそのカーネルの紹介

トライデント コア: IE、MaxThon、TT、The World、360、Sogou Brows...

Vue プロジェクトのパッケージ化、マージ、圧縮により、Web ページの応答速度を最適化します。

目次序文1. リクエスト内容が大きすぎる解決: CDN の紹介リクエストリソースを圧縮する1. HT...

Mysql一時テーブルの原理と作成方法の分析

この記事は主にMysql一時テーブルの原理と作成方法を紹介します。この記事のサンプルコードは非常に詳...

Mac OS 10.11 での MySQL 5.7.12 のインストールと設定のチュートリアル

Mac OS 10.11 に MySQL をインストールして設定する方法を、主に写真を使って手順を簡...

JavaScript DOMContentLoaded イベントのケーススタディ

DOMContentLoaded イベント文字通り、DOM がロードされた後に実行されます。 win...

MySQL複合インデックスの概要

目次1. 背景2. 複合インデックスを理解する3. 左端一致原則4. フィールド順序の影響5. 単一...

Java で ffmpeg を呼び出してビデオ形式を flv に変換する方法の詳細な説明

Java で ffmpeg を呼び出してビデオ形式を flv に変換する方法の詳細な説明注:以下のプ...

VMware WorkStation を Docker for Windows で使用するための詳細なチュートリアル

目次1. はじめに2. Windows用Dockerをインストールする1. Windows用Dock...

JavaScript フロー制御 (分岐)

目次1. プロセス制御2. シーケンシャルプロセス制御3. 分岐フロー制御if文1. 支店構造2. ...

完全なショッピングカートを実装するためのミニプログラム

ミニプログラムは、参考までに完全なショッピングカート[すべて選択/選択解除して金額を計算/加算と減算...

フォームタグの Enctype 属性とその応用例の紹介

Enctype : ブラウザがデータをサーバーに送り返すときに使用するエンコーディングのタイプを指定...

OpenSSL は双方向認証のチュートリアルを実装します (サーバーとクライアントのコード付き)

1. 背景1.1 問題点最近の製品テスト レポートでは、PKI ベースの認証方法の使用が推奨されて...

HTML メタタグの小さなコレクション

<Head>……</head> は <HTML> のファイル ヘ...

Linux カーネル デバイス ドライバー Linux カーネル 基本メモの概要

1. Linuxカーネルドライバモジュールの仕組み静的ロードでは、ドライバモジュールをカーネルにコン...