背景 最近、SQL 文を書くときに、IN と Exists のどちらを選択するか迷ったので、両方の方法の SQL を書き出して実行効率を比較してみました。IN のクエリ効率は Exists よりもはるかに高いことがわかったので、IN の効率は Exists よりも優れていると自然に思いました。しかし、物事の真相を突き止めるという原則に沿って、この結論がすべてのシナリオに当てはまるかどうか、またなぜこのような結果になるのかを知りたいです。 実験データ 私の実験データには、t_author テーブルと t_poetry テーブルの 2 つのテーブルが含まれています。 t_author テーブル、13355 件のレコード; 対応するテーブル構造は次のとおりです。
実行プロセスにおける実行計画分析 SQL の例: 実行計画: 実行プロセスが存在する SQL の例: 実行計画: (1)まずtabAテーブルからすべてのレコードを取得します。 実験手順 この実験では、同じ結果セットの IN および Exists SQL ステートメントを分析します。
Exists を含む SQL ステートメント:
最初の実験のデータ t_author テーブル、13355 件のレコード。t_poetry テーブル、poetry_id>293650 のサブクエリ フィルター結果セット、121 件のレコード。 実行結果 exists を使用すると 0.94 秒かかり、in を使用すると 0.03 秒かかります。INは Exists よりも効率的です。 原因分析 t_poetry テーブルのサブクエリの結果セットは非常に小さく、どちらも t_poetry テーブルのインデックスを使用でき、t_poetry サブクエリの消費量は基本的に同じです。 2 つの違いは、in を使用する場合、t_author テーブルはインデックスを使用できることです。 exists を使用すると、t_author テーブルが完全にスキャンされます。 サブクエリの結果セットが小さい場合、クエリ時間は主に t_author テーブルのトラバーサルに反映されます。 2番目の実験データ t_author テーブル、13,355 件のレコード。t_poetry テーブル、poetry_id>3650 のサブクエリ フィルター結果セット、287,838 件のレコード。 実行時間 exists を使用すると 0.12 秒かかり、 in を使用すると 0.48 秒かかります。 Exists は IN よりも効率的です。 原因分析 2 つの実験のインデックスの使用法は、最初の実験と一致しています。唯一の違いは、サブクエリ フィルタリング結果セットのサイズです。ただし、実験結果は最初のものとは異なります。この場合、サブクエリの結果セットは非常に大きくなります。MySQL クエリ プランを見てみましょう。 exists を使用する場合、データ量の変化によって実行プランは変わりません。ただし、サブクエリの結果セットが大きいため、MySQL バージョン 5.5 以降では、exists のクエリ結果をマッチングするときに Block Nested-Loop (ブロック ネスト ループ、結合バッファを導入、キャッシュ機能に類似) が使用されます。これは、クエリの効率に大きな影響を与え始め、特にサブクエリの結果セットが大きい場合は、クエリのマッチング効率を大幅に向上させることができます。 実験的結論 上記の 2 つの実験とその結果に基づいて、IN と Exists の実行プロセスを明確に理解し、IN と Exists の適用可能なシナリオをまとめることができます。 IN クエリは内部テーブルと外部テーブルの両方でインデックスを使用できますが、Exists クエリは内部テーブルでのみインデックスを使用できます。サブクエリの結果セットが大きく、外部テーブルが小さい場合、Exists のブロック ネスト ループが役割を果たし始め、外部テーブルでインデックスを使用できないという欠点を補い、クエリの効率は IN よりも高くなります。サブクエリの結果セットが小さく、外部テーブルが大きい場合、Exists のブロック ネスト ループの最適化効果は明らかではなく、IN の外部テーブル インデックスの利点が大きな役割を果たします。この場合、IN のクエリ効率は Exists よりも優れています。オンラインで言われていることは不正確です。実際、「テーブルのサイズ」は内部テーブルと外部テーブルではなく、外部テーブルとサブクエリの結果セットを指します。最後のポイントは最も重要な点でもあります。世界には絶対的な真実はありません。物事の本質を把握し、さまざまなシナリオで実践的な検証を行うことが、最も信頼性が高く効果的な方法です。 実験中に発見された問題に関する補足情報 異なるデータ セットで上記の存在するステートメントを分析すると、データ セットが大きいほど、消費時間が短くなることが分かりました。これは非常に奇妙なことです。
考えられる理由: 条件値が大きいほど、クエリが遅くなり、走査するレコードの数が増え、消費時間が長くなります。この説明はさらに検証する必要がある。 以下もご興味があるかもしれません:
|
<<: Linux で実行中のバックグラウンド プログラムを表示および終了する方法
主な違いは次のとおりです。 1. MySQL はデフォルトで MyISAM を使用します。 2. M...
この記事では主に、高さが不明な垂直方向の中央揃えを CSS で実装する方法を紹介し、皆さんと共有しま...
この記事の例では、参考までに簡単な計算機を実装するためのjsの具体的なコードを共有しています。具体的...
データ共有プロトタイプにはどのようなデータを書き込む必要がありますか?共有する必要があるデータはプロ...
表ラベルの構成HTML 内の表は <table> タグで構成されており、ブラウザはタグを...
CSS 位置position 属性は、要素の配置タイプを指定します。位置プロパティには 5 つの値が...
1. 概要Zabbix は非常に強力で、最も広く使用されているオープンソースの監視ソフトウェアです。...
目次前面に書かれた解決策 1: グローバル スタイル オーバーライドを使用する (フロントエンドに共...
まずサンプルコードを見てみましょう: #/bin/bash cal 日付 -u echo "...
MySQL 5.7.8 以降では、JSON テキストでデータを効率的に取得できるネイティブ JSON...
目次ノードはMysqlに接続しますMySQLモジュールをインストールするMySQLに接続するよく使わ...
1. 最初の方法は、unhup コマンドを直接使用してプログラムをバックグラウンドで実行することです...
序文最近、オンラインでデータが誤って操作されました。データベースが直接変更されたため、それを回復する...
目次導入準備するシステムイメージをダウンロードHyper-Vを有効にする新しい仮想ネットワークスイッ...
CSS3 アニメーション トランジションを使用して、リンクの上にマウスを移動すると小さなポップアップ...