クエリ 1 は、テーブルのプライマリ キー インデックスを調べて、正しい 600,000 の ID とテーブル内の対応する場所を見つけ、次にテーブルに移動し、それらの 600k の場所からすべてをフェッチします。
クエリ 2 は、テーブルの主キー インデックスを調べ、正しい 600k ID とテーブル内の対応する場所を見つけてから、テーブルに移動し、それらの 600k 行から要求されたフィールドのサブセットをフェッチします。
クエリ 3 は、テーブルの主キー インデックスを調べて、正しい 600k ID を見つけ、それらを返します。表を見る必要はまったくありません。
クエリ 4 は、テーブルの主キー インデックスを調べ、要求された単一のエントリを見つけ、テーブルに移動し、その単一のエントリを読み取り、それを返します。
時間的に、逆方向に構築しましょう。
(Q4) テーブル インデックスを使用すると、O(log n) 時間でキー (id) を検索できます。つまり、テーブルのサイズが 2 倍になるたびに、インデックス内のキーを見つけるために 1 つの追加ステップしか必要としません*。100 万行ある場合、それを見つけるのに 20 ステップしかかかりません。10億行?30歩。インデックス エントリには、その行のデータを見つけるためにテーブル内のどこに移動するかに関するデータが含まれているため、MySQL はテーブル内のその場所にジャンプして行を読み取ります。これについて報告された時間は、ほぼ完全にオーバーヘッドです。
(Q3) 前述のとおり、テーブル インデックスは非常に高速です。このクエリは最初のエントリを見つけ、要求された行数になるまでツリーをトラバースします。必要なステップ数を正確に計算できると確信していますが、最大で 20 ステップ x 600k 行 = 12M ステップとします。ツリーをトラバースしているので、1M ステップのようになる可能性がありますが、正確な数はほとんど関係ありません。ここで認識すべき最も重要なことは、MySQL がインデックスを調べて必要な ID を取得すると、必要なものがすべて含まれているということです。テーブルを見に行く必要はありません。これについて報告された時間は、基本的に、MySQL がインデックスを移動するのにかかる時間です。
(Q2) これは、クエリ 3 で説明したのと同じツリー ウォークから始まりますが、必要な ID を取得するときに、MySQL はテーブル ファイル内のそれらの場所も取得します。次に、テーブル ファイル (おそらく既にmmap
メモリにキャッシュ/ペディングされている) に移動し、プルされたすべてのエントリに対して、テーブル内の適切な場所を探し、それらの行から要求されたフィールドを取得する必要があります。このクエリで報告された時間は、インデックスを移動するのにかかる時間 (第 3 四半期と同様) に、インデックスで指定されたすべての行にアクセスするのにかかる時間を加えたものです。
(Q1) すべてのフィールドが指定されている場合、これは Q2 と同じです。時間は基本的に第 2 四半期と同じであるため、インデックスをクロールして行をシークすることによって小さくなった場合はいつでも、データベースからより多くのフィールドを取得するのにそれほど時間がかからないことがわかります。
*: ほとんどのデータベースは、対数ベースが 2 よりはるかに大きいインデックス データ構造 ( MySQLの場合は B ツリー) を使用します。数百倍から数千倍になります。これは、例で述べた 20 ~ 30 ステップではなく、2 ~ 5 ステップに近いことを意味します。