質問
SQLのoffset句のアルゴリズムを解説してください |
解答
SQLの `OFFSET` 句は、クエリ結果の先頭から指定した件数だけスキップしてから結果を返す仕組みです。 ページネーションなどに使われることが多いです。 ただし、内部的な動作(アルゴリズム)を理解すると、「便利だけど効率が悪くなる場合がある」こともわかります。 ✅ 基本構文と用途 ```sql SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20; ``` → `id` の昇順でソートされた結果のうち、21件目から10件を取得します。 ✅ OFFSET のアルゴリズム的な動作 SQLエンジン内部では、以下のような手順が取られます(PostgreSQLやMySQLなどの一般的な実装に基づく): 1. WHERE句による絞り込み 2. ORDER BY でソート 3. OFFSET の件数までスキャンしてスキップ 4. LIMIT で指定された件数だけ返す つまり… * 実際には、LIMIT + OFFSET の合計分の行が必要 * たとえば `LIMIT 10 OFFSET 10000` の場合、少なくとも10010件を読み込んで、そのうち最初の10000件を破棄します ✅ OFFSET のパフォーマンス問題 ◾ 問題点 * 大きな OFFSET 値になると、スキャン・ソート・破棄の処理が非常に重くなる * 結果的に「必要のない大量の行」を読み込んで無駄にしてしまう ◾ 実際の例 ```sql -- ページネーションでよくある構文 SELECT * FROM articles ORDER BY created_at DESC LIMIT 20 OFFSET 100000; ``` → インデックスがあっても、100020件分の行をスキャンしなければならない可能性がある ✅ 効率化の代替手法(オススメ) 1.カーソル(keyset pagination)を使う ```sql -- 前回取得したlast_idを使って次のページを取得 SELECT * FROM users WHERE id > :last_id ORDER BY id ASC LIMIT 10; ``` 2.インデックスが使える列を使ってフィルタリング * OFFSET ではなく「範囲指定」によってスキップ * ソートと一致するインデックスが有効に働く ✅ まとめ
|
|
|
この記事へのコメント