2013-07-23 5 views
6

シンプルで非常に大きなInnodbテーブルでは、カラムAにユニークなインデックスがあり、整数Bのリストを(整数)カラムAの順に取得したい。MySQL Innodbがユニークインデックスが存在するときに「ソートインデックスを作成する」のはなぜですか?

数百万のレコードをページングします。

SELECT B FROM hugeTable ORDER BY A LIMIT 10000 OFFSET 500000

これは非常に高速なサーバー上のクエリごとに10秒かかりますか?

Filesort: Yes Filesort_on_disk: Yes Merge_passes: 9

これは私には意味をなさない、なぜそれがインデックスAを使用することはできませんか?

説明は簡単で、可能なキーとファイルはありません。

答えて

10

インデックスページでB列の値を使用できない場合、MySQLは基になるテーブルのページにアクセスする必要があります。また、どの行が考慮されているかを示す述語もありません。つまり、MySQLはすべての行を返す必要があることを認識しています。これは、索引が使用されていない理由を説明することができます。

LIMIT操作は、実行計画の最後のステップに近いように、いくつかの例外を除いて、ステートメントの最後に処理されます。

8.2.1.3. Optimizing LIMIT Queries http://dev.mysql.com/doc/refman/5.5/en/limit-optimization.html

私はあなたのクエリがソート操作を回避するために、例えば、被覆インデックスの「ON hugetable (A,B)」を利用することができることを疑います。

カバリングインデックスがない場合は、次のようなクエリを書き換えて、A列のインデックスを使用するかどうかを確認し、何百万行もの並べ替え操作を行わないようにすることができます)ために:私はあなただけのインライン・ビューのクエリにEXPLAINを行う示唆

SELECT i.B 
    FROM (SELECT j.A 
      FROM hugeTable j 
      ORDER 
      BY j.A 
      LIMIT 10000 OFFSET 500000 
     ) k 
    JOIN hugetable i 
    ON i.A = k.A 
ORDER 
    BY k.A 

()kとエイリアス、およびそれが示している場合参照「Using indexを。」

外部クエリにはまだ "Using filesort"操作が含まれている可能性がありますが、少なくとも10,000行にしかなりません。

(注:それが違いを作る場合は、外側のクエリに "k.A" の代わりに "ORDER BY i.A" してみてください、と見てみたいことがあります。)


補遺

あなたの質問に具体的に対処するのではなく、そのクエリのパフォーマンスに関して、これが「ページングスルー」の行セットである場合、「次の」ページに移動するための別のオプションは、「A」の値を使用することです前の問合せで検索された最後の行は、tの「開始点」として彼は次の行。

元のクエリは「ページ51」(ページあたり10,000行、ページ51は行510,001〜520,000)になっているように見えます。

また、 'A'の値を返す場合は、最後の行を保持してください。「次」のページを取得するには、クエリが実際に次のようになります。あなたも「最初」の行からAの値を保持していた場合

SELECT i.B, k.A 
    FROM (SELECT j.A 
      FROM hugeTable j 
      WHERE j.A > $value_of_A_from_row_520000 
     -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
      LIMIT 10000 
     ) k 
    JOIN hugetable i 
    ON i.A = k.A 
    ORDER 
    BY k.A 

、あなたはページをバックアップするためのものを使用することができます。それは実際には、前の1ページまたは後ろの1ページでのみ機能します。別のページにジャンプすると、行の数をカウントして元のクエリの形式を使用する必要があります。

関連する問題