2012-03-14 4 views
5

2百万以上のレコードを持つ "users"テーブルを使用しています。クエリは次のとおりです。ORDER BY LIMITクエリのMySQLインデックス使用方法

SELECT * FROM users WHERE 1 ORDER BY firstname LIMIT $start,30 

"firstname"列がインデックスに登録されています。最初のページの取得は非常に高速ですが、最後のページの取得は非常に遅いです。

私は取得しています

EXPLAIN SELECT * FROM `users` WHERE 1 ORDER BY `firstname` LIMIT 10000 , 30 

用:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE users index NULL firstname 194  NULL 10030 

しかし、私は取得しています

EXPLAIN SELECT * FROM `users` WHERE 1 ORDER BY `firstname` LIMIT 100000 , 30 

ため

私は結果であり、ここでEXPLAINを使用し、

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE users ALL  NULL NULL NULL NULL 2292912  Using filesort 

問題点を教えてください。

+0

あまりにも多くスキップします。 –

+0

'ANALYZE TABLE users'文を実行して、それが役立つかどうか確認してください。 –

答えて

3

データセットのページまではページを制限しないでください。

範囲クエリを使用すると、より多くの結果が得られます。

last_used_nameあなたはすでに(私はあなたには、いくつかの並べ替えのバッチ処理を行うことを仮定している)見たものです
SELECT * FROM users 
WHERE firstname >= last_used_name 
ORDER BY firstname 
LIMIT 30 

。一意のインデックスを持つ列に対して範囲クエリを実行すると、より正確な結果が得られます。この方法で同じレコードを2回取得することはありません。

あなたが

LIMIT 100000 , 30 

MySQLは、本質的にのみ、それは最初の100数千人を返さない

LIMIT 100030 

と同様に行います。しかし、それは並べ替えて、それらを読み取ります。

+0

答えをありがとう。私はリストを改ページするためにこれを使用しています。リンクを作成するためにlast_used_nameを取得すると、コードが難しくなります。いくつかの良い解決策を得ることが幸せだろう – user1270172

+0

無料のランチなどのようなものはありません、あなたは知っています。あなたのコードを最適化するか、遅い 'LIMIT'に苦しんでいます。私はこのポストを見守りますが、おそらく他の解決策が出てくるでしょう。 –

0

WHERE条件なしの*クエリでは、MySQLではインデックスを使用しないことがよくあります。

次のクエリでは、はるかに高速であることと、インデックスの使用を行う必要があります

SELECT * 
FROM (
    SELECT user_id 
    FROM users 
    WHERE 1 
    ORDER BY firstname 
    LIMIT $start, 30) ids 
JOIN users 
USING (user_id); 

user_idは主キーです。

関連する問題