大きなテーブルでOFFSET
を使用するとパフォーマンスが低下することは、さまざまなブログで広く議論されています。最も効率的な方法は、INNER JOIN
を次のように使用することです
SELECT *
FROM table
INNER JOIN (
SELECT id
FROM table
LIMIT 10 OFFSET 100000)
AS results USING(id);
しかし、単純なサブクエリに対するINNER JOIN
の利点は何ですか?
SELECT *
FROM table
WHERE id >
(SELECT id
FROM table
LIMIT 1 OFFSET 100000)
LIMIT 10;
以上便利
SELECT *
FROM table
WHERE id IN
(SELECT id
FROM table
LIMIT 10 OFFSET 100000);
次の例では、ORDER BY
が主キーであると想定されていますが、他の順序やWHERE
句を追加することもできます。私の質問は、INNER JOIN
または単純なサブクエリ `のパフォーマンスの比較についてです。
あなたの特定のケースでは、代わりに_LEFT JOIN
_を使用します。どうして?
_LEFT JOIN
_クエリでは、必要なキーとフェッチして結合する順序を指定できますが、_INNER JOIN
_を使用すると、MySQLクエリオプティマイザーが最適なキーを決定できます。場合によっては、EXPLAINプランは恐ろしいように見えるかもしれませんが、それでも優れたパフォーマンスを提供します。
の代わりに
_SELECT *
FROM table
INNER JOIN (
SELECT id
FROM table
LIMIT 10 OFFSET 100000)
AS results USING(id);
_
最初にキーを持つようにクエリを反転します
_SELECT B.*
FROM (SELECT id FROM table LIMIT 10 OFFSET 100000) A
LEFT JOIN table B USING (id);
_
そこから、サブクエリA内で順序を制御できます
_SELECT B.*
FROM (SELECT id FROM table LIMIT 10 OFFSET 100000 ORDER BY ...) A
LEFT JOIN table B USING (id);
_
またはUSING (id)
の後
_SELECT B.*
FROM (SELECT id FROM table LIMIT 10 OFFSET 100000) A
LEFT JOIN table B USING (id) ORDER BY ...;
_
このように、実際のデータを見つける前に、キーをナビゲート(またはページネーション)できるはずです。経験的な証拠を使用してこれを示すには、プライマリキーで_LEFT JOIN
_を使用することに関する私のStackOverflowの投稿( 結合テーブルからの単一行のフェッチ )を参照してください。