MySQLインデックスの最適化(2)


小さなテーブルが大きなテーブルを動かす

ここに画像の説明を挿入

ORDERBY最適化

シミュレーションデータ

create table tblA(
#id int primary key not null auto_increment,
age int,
birth timestamp not null
);

insert into tblA(age, birth) values(22, now());
insert into tblA(age, birth) values(23, now());
insert into tblA(age, birth) values(24, now());

create index idx_A_ageBirth on tblA(age, birth);

実行計画を表示する

ケースA

EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY age
EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY age,birth
EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY birth
EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY birth,age
EXPLAIN SELECT * FROM tblA WHERE birth > '2021-02-19 22:45:00' ORDER BY birth
EXPLAIN SELECT * FROM tblA WHERE birth > '2021-02-19 22:45:00' ORDER BY age

ここに画像の説明を挿入

ケースB

EXPLAIN SELECT * FROM tblA ORDER BY age ASC,birth DESC 

ここに画像の説明を挿入

結論として

  • MySQLは、インデックスとファイルソートの2つのソート方法をサポートしています。インデックスは非常に効率的です。つまり、スキャンインデックス自体がソートされ、ファイルソートは非効率的です。
  • ORDER BY句、並べ替えにインデックスを使用してみてください。並べ替えにファイルソートを使用しないでください。
  • ORDER BY句は2つの条件を満たすため、インデックスの並べ替えが使用されます。1つは、ORDER BY句が最良の左プレフィックスルールを採用すること、もう1つは、where条件フィールドとORDERBY句を組み合わせて最良の左プレフィックスを満たすことです。ルール。
    並べ替えとグループ化の最適化

MySQLソートアルゴリズム

ファイルソートの使用が発生すると、MySQLは独自のアルゴリズムに従ってクエリ結果をソートします

双方向ソート

  • MySQL 4.1より前は、双方向ソートが使用されていました。これは、文字通りディスクを2回スキャンし、最後にデータを取得し、行ポインターと列順を読み取り、それらをソートしてから、ソートされたリストをスキャンして、再起動することを意味します。リスト内の値に従ってデータを取得します。リスト内の対応するデータ出力を読み取ります。
  • ディスクから並べ替えフィールドを取得し、バッファで並べ替えてから、ディスクから他のフィールドをフェッチします。
    簡単に言うと、データのバッチをフェッチするには、ディスクを2回スキャンする必要があります。ご存知のとおり、I \ Oは非常に時間がかかるため、mysql4で。1の後、2番目の改善されたアルゴリズムが登場しました。これは一方向のソートです。

一方向ソート

  • クエリに必要なすべての列をディスクから読み取り、列の順序に従ってバッファ内で並べ替えてから、並べ替えられたリストをスキャンして出力します。これにより、データの再読み込みが回避され、高速になります。また、ランダムIOをシーケンシャルIOに変換しますが、各行をメモリに保存するため、より多くのスペースを使用します。

問題

  • sort_bufferでは、メソッドBがすべてのフィールドを取得するため、メソッドBはメソッドAよりもはるかに多くのスペースを占有します。したがって、抽出されたデータの合計サイズがsort_bufferの容量を超え、結果としてsort_bufferのサイズのみになる可能性があります。毎回データ。、ソートを実行し(tmpファイルの作成、マルチチャネルマージ)、ソート後にsort_buffer容量を取得し、再度ソートします...したがって複数のI / O。つまり、1つのI / O操作を節約したかったのですが、それによって多数のI / O操作が発生しましたが、利益は損失の価値がありませんでした。

最適化する方法

  • sort_buffer_sizeパラメータ設定を増やしてください

    どのアルゴリズムを使用する場合でも、このパラメータを改善すると効率が向上します。もちろん、このパラメータはプロセスごとに1M〜8Mの間で調整されるため、システムの能力に応じて改善する必要があります。

  • max_length_for_sort_dataパラメータ設定を増やしてください

    一方向ソートを使用するmysqlの前提は、ソートされたフィールドのサイズがmax_length_for_sort_dataよりも小さいことです。このパラメーターを増やすと、改善されたアルゴリズムを使用する可能性が高くなります。

    ただし、設定が高すぎると、合計データ容量がsort_buffer_sizeを超える可能性が高くなり、結果として高頻度のディスクI / O低いプロセッサ使用率が発生します。(1024-8192の間で調整)
    まとめ

  • 選択後のクエリフィールドを減らします(select *を少なく使用します)

    クエリフィールドの数を減らすと、バッファはより多くのコンテンツを保持できます。これは、sort_buffer_sizeを間接的に増やすことと同じです。

まとめA

ここに画像の説明を挿入

まとめB

ここに画像の説明を挿入

GROUPBY最適化

GROUP BYの最適化は、ORDERBYとほぼ同じです。
ここに画像の説明を挿入

  • 並べ替え時にインデックスを使用し、filesortの使用を避けたい場合は、インデックスカバレッジを使用できます
  • ORDER BY / GROUP BYの後のフィールドの順序は、複合インデックスの順序とまったく同じである必要があります
  • ORDER BY / GROUP BYの後のインデックスは順番に表示される必要があり、その後のインデックスは表示されない場合があります
  • 昇順または降順を実行するには、フィールドの並べ替え順序が一貫している必要があります。昇順の一部ではなく、降順の一部、昇順の両方、またはすべての降順
  • 複合インデックスの前のフィールドがフィルター条件で定数として表示される場合、ソートフィールドはその直後のフィールドになります。

おすすめ

転載: blog.csdn.net/single_0910/article/details/113873323