この記事では、MySQL におけるキーワードの原則を比較的マクロな観点から見ていきます。この記事では、主に order by ステートメントの基本原則について説明します。この記事を読むと、次のことがわかります。 order by ステートメントのソート モードと、各ソート モードの長所と短所は何ですか。 order by ステートメントではどのソート アルゴリズムが使用されるか、また、どのようなシナリオでどのソート アルゴリズムが選択されるか。 最適化方法 (実行プラン + OPTIMIZER_TRACE ログ) による SQL の順序を表示および分析する方法。 order by ステートメントの実行効率を最適化するにはどうすればよいでしょうか? (考え: 行サイズを減らし、インデックスを使用するようにし、カバーリング インデックスを使用するのが最善で、ソート バッファーのメモリ サイズを適切に増やします) ここでは、データとインデックスをデータ構造の観点から見ていきます。つまり、それらはすべて B+ ツリーであると考えられます。データが必要な場合は、ストレージ エンジンの B+ ツリーからデータを読み取ります。 以下は、この記事でデモンストレーションの例として使用する表です。次の表があるとします。 インデックスは次のとおりです。 対応する idx_d インデックス構造は次のとおりです (ここでは、インデックス ツリーでの検索プロセスを示すために、データ ページを小さくするために多少誇張しています)。 1. 実行の最適化を追跡する方法 SQL 実行プロセスの分析を容易にするために、現在のセッションで optimizer_trace を有効にすることができます。
次に、SQL を実行します。実行後、次のスタック情報を通じて実行の詳細を表示できます。
以下は
実行結果には、a=3 に一致するレコードが 8457 件あることが示されています。order by では、次の属性に注目します。
1.1. ソートモード sort_mode には次の形式があります。
並べ替えモードの選択方法 ソート モードの選択は max_length_for_sort_data 属性に関連しており、デフォルト値は 1024 バイトです。
1.2 ソートアルゴリズム ソートに関係するデータの量に基づいて、さまざまなソート アルゴリズムを選択できます。
2. Order byはソートを避けるためにインデックスを使用する 次のSQLを実行します。
実行計画を見てみましょう。 Extra 列には「Using index condition」と表示されており、ここではインデックスのみが使用されていることがわかります。 実行フローは次の図に示されています。 idx_d インデックスを介して range_scan 検索を実行し、4 つのレコードをスキャンします。次に、order by は、すでに順序付けされているインデックスを引き続き使用し、最初の 2 つのレコードを直接取得します。次に、クラスター化インデックスを使用して完全なレコードをクエリし、クエリ結果として最終的な必須フィールドを返します。このプロセスではインデックスの助けだけが必要です。 ソート バッファ サイズを表示および変更するにはどうすればよいですか? 現在のソート バッファ サイズを見てみましょう。 ソート バッファ サイズはデフォルトで 512k に設定されていることがわかります。 このプロパティのサイズを設定できます:
次に、ソートバッファを32kに均一に設定します。
3. ソートアルゴリズムの例 3.1. ヒープソートに優先キューを使用する ソートの結果が小さく、ソート バッファーよりも小さい場合は、優先キューがヒープ ソートに使用されます。 たとえば、次の例では最初の 10 件のレコードのみが取得されます。
a=3 のレコードの合計数: 8520。実行プランを表示します。 where 条件ではインデックスが使用され、order by 制限ではソートが使用されることがわかります。実行の optimizer_trace ログを詳しく見てみましょう。
ここでは、ソートに優先キューが使用されていることがわかります。ソート モードは sort_key、additional_fields です。つまり、最初にテーブルに戻って完全なレコードを照会し、ソートに必要なすべてのフィールドをソート バッファーに入れてソートします。 実行フローは次のようになります。
3.2 内部クイックソート ソート制限 n、m、n が大きすぎる場合、つまりソートの最後にデータを取得する必要がある場合は、クイックソートにソートバッファーが使用されます。 MySQL は、優先キュー ソートとマージ ソートのオーバーヘッドを比較し、より適切なソート アルゴリズムを選択します。 優先キューを使用するか、メモリ内クイックソートを使用するかをどのように決定しますか? 一般的に言えば、クイック ソート アルゴリズムはヒープ ソートよりも効率的ですが、ヒープ ソートによって実装された優先キューは、すべての要素をソートしなくても order by limit の結果を取得できます。 MySQL のソースコードによると、クイックソートはヒープソートより 3 倍高速です。実際のソート時には、ソートする項目の数に応じてアルゴリズムが切り替えられます。データの量が多すぎる場合は、代わりにクイックソートが使用されます。 次のSQLがあります:
ソートバッファを 32k に設定します。
a=1 のレコードが 3 つあります。実行プランを表示します。 where 条件ではインデックスが使用され、order by 制限ではソートが使用されることがわかります。実行の optimizer_trace ログを詳しく見てみましょう。
ここで、優先キューは最終的に放棄され、代わりにソート バッファーがクイック ソートに使用されていることがわかります。 実行フローは次のようになります。
3.3 外部マージソート ソートするデータが多すぎて、ソート バッファーに一度に格納できない場合は、メモリ内のソート バッファーをバッチでソートし、その結果を一時ソート ファイルに格納し、最後にソートされたすべての一時ファイルをマージしてソートし、最終結果を取得します。 次のSQLがあります:
a=3 のレコードは 8520 件あります。実行計画は次のとおりです。 画像-20200614171147989 where はインデックスを使用し、order by limit はソートを使用していることがわかります。さらに、実行の optimizer_trace ログを表示します。
1000 という制限があるため、ソート後に 1000 行後のレコードを返すには、ソート バッファーがこのような大きな優先キューをサポートできなくなるため、代わりにソート バッファー メモリ ソートが使用されることがわかります。ここでは、ソート バッファー内でクイック ソートをバッチで実行して、複数のソートされた外部一時ファイルを取得し、最後にマージ ソートを実行する必要があります。 (外部一時ファイルの場所はtmpdirパラメータで指定されます) プロセスを次の図に示します。 4. ソートモードの例 4.1、sort_key、additional_fields モード sort_key、additional_fields、ソート バッファ タプルには、ソート キー値とクエリに必要な列が含まれます (最初にテーブルに戻って必要なデータを取得し、ソート バッファに格納します)。ソート後、データはテーブルに戻らずにバッファ タプルから直接取得されます。 上記のセクション 2.3.1 と 2.3.2 の例はすべてこのソート モードを使用しているため、これ以上の例は示しません。 4.2 モード sort_key、packed_additional_fields: 前の形式と似ていますが、固定長エンコードを使用する代わりに、追加の列 (varchar 型など) が密にパックされます。 上記のセクション 2.3.3 の例は、このソート モードです。ソートに関係するレコードの合計サイズが大きすぎるため、メモリを節約するために追加の列を密に詰める必要があります。 4.3 モード 前述のように、ソートモードの選択は、ソートされた行の最大サイズを指定するmax_length_for_sort_data[2]属性に関連しています。この属性のデフォルト値は1024バイトです。 つまり、クエリ列とソート列が占めるサイズがこの値より小さい場合は、sort_key、additional_fields または sort_key、packed_additional_fields アルゴリズムが使用されます。それ以外の場合は、代わりに sort_key、rowid モードが使用されます。 ここで、sort_key、rowid モードをシミュレートするために、この値を意図的に小さい値に設定します。
この時点でSQLを実行します:
この時点で、SQL 実行の optimizer_trace ログを確認します。
モードが sort_key、rowid モードに切り替わっていることがわかります。このモードでは、実行プロセスは次のようになります。
行レコードが大きすぎるため、ソート バッファーにはソートが必要なフィールドと主キー ID のみが格納されていることがわかります。時間とスペースが交換されます。最後に、ソートが完了し、必要なすべてのフィールドがクラスター化インデックスから再度検索され、クライアントに返されます。明らかに、テーブルを返す操作のために追加のディスク読み取りがあり、全体的な効率はわずかに低下します。 5. 順序最適化のまとめ 上記の紹介に基づいて、order by ステートメントの最適化方法を次のようにまとめることができます。
参考文献 [1]: Didi Cloud。MySQLのフルテーブルCOUNT(*)の簡単な説明。zhihu.com。https://zhuanlan.zhihu.com/p/54378839から取得 [2]: MySQL. 8.2.1.14 ORDER BY最適化。https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.htmlから取得 [3]: MySQL: ソートの詳細な分析 (filesort)。https://www.jianshu.com/p/069428a6594e から取得 [4]: ORDER BY LIMITと優先キュー(ヒープソート)のMYSQL実装。http://blog.itpub.net/7728585/viewspace-2130920/から取得 この記事はWeChatの公開アカウント「Java Architecture Talk」から転載したものです。以下のQRコードからフォローできます。この記事を転載する場合は、Java Architecture Talk のパブリック アカウントにお問い合わせください。 ブログアドレス: https://www.itzhai.com |
>>: AI と ML はデータの理解方法をどのように変えているのでしょうか?
導入ソートとは、データのセットを指定された順序で並べるプロセスです。分類カテゴリ内部ソート: ソート...
開発者、ライター、または AI 愛好家であれば、ChatGPT の開発元である OpenAI の最新...
51年前、アポロ13号が宇宙に打ち上げられました。打ち上げ直後、宇宙船は大きな爆発に遭遇した。宇宙船...
スタンフォード大学のAI 100のAI Indexプロジェクトは、人工知能の活動と進歩を追跡し、人工...
この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...
今週の月曜日も、他の月曜日と同様に、Spotify の 1 億人を超えるユーザー全員に新しいプレイリ...
人工知能などの技術の発展により、無人技術がますます多く登場しています。 2030 年までに、8 億人...
デジタル経済の発展に伴い、全国の各省市がコンピューティングインフラの構築を競って推進し、人工知能コン...
アルゴリズムを実装する場合、アルゴリズムの複雑さは通常、時間の複雑さと空間の複雑さという 2 つの側...
ロシアのスプートニク通信は12月17日、米空軍が最近、U2戦闘機の副操縦士として初めて人工知能を使用...