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の後のインデックスは順番に表示される必要があり、その後のインデックスは表示されない場合があります
- 昇順または降順を実行するには、フィールドの並べ替え順序が一貫している必要があります。昇順の一部ではなく、降順の一部、昇順の両方、またはすべての降順
- 複合インデックスの前のフィールドがフィルター条件で定数として表示される場合、ソートフィールドはその直後のフィールドになります。