web-dev-qa-db-ja.com

単純なサブクエリによる大きなテーブルでのOFFSETの使用

大きなテーブルで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または単純なサブクエリ `のパフォーマンスの比較についてです。

2
Googlebot

あなたの特定のケースでは、代わりに_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の投稿( 結合テーブルからの単一行のフェッチ )を参照してください。

試してみる !!!

1
RolandoMySQLDBA