【りみっと おふせっと】
LIMIT / OFFSET とは?
最終更新:
💡 順序を決めて、必要な範囲の行を取り出す
LIMITは取得する最大行数、OFFSETは結果の先頭から飛ばす行数を指定するSQLの句。ページ送りでは一意に決まるORDER BYが重要です。大きなOFFSETの負担と、続きのキーから取得する方法も解説します。
📌 このページのポイント
- LIMITは最大行数、OFFSETは先頭から飛ばす行数を指定する
- ページ送りではORDER BYで一意に決まる順序を指定する
- 飛ばす行も処理が必要なので、大きなOFFSETは非効率になる場合がある
- 続きのキーを使う方法もあるが、適切な索引と順序の設計が必要
LIMITとOFFSETはどう違うの?
LIMITは返す最大行数、OFFSETは結果の先頭から飛ばす行数だよ。例えばidが一意なproductsでORDER BY id LIMIT 10 OFFSET 20なら、id順に並べた結果の最初の20行を飛ばし、次の最大10行を返す。idが21から始まるという意味ではないんだ。
ORDER BYも必要なの?
ページ送りなら順序を決めよう。ORDER BYがなければSQLは行の順序を保証しない。価格だけで並べると同額の行の順序が決まらないので、ORDER BY price, idのように一意なキーも加える。そうしないとページ間で重複や取りこぼしが起きやすいよ。
1ページ10件ならどう指定する?
同じ順序で1ページ目はLIMIT 10 OFFSET 0、2ページ目はOFFSET 10、3ページ目はOFFSET 20だね。ただし途中で行が追加・削除されると位置がずれる。順序を決めても、別々の時点の結果がずっと同じとは限らないんだ。
後ろのページは遅くなるの?
PostgreSQLの公式資料では、OFFSETで飛ばす行もサーバー内で計算が必要なので、大きな値は非効率になり得ると説明しているよ。実際の負担は条件、索引、データ量や実行計画による。LIMITが小さければ処理も必ず少ない、とは限らないね。
OFFSET以外の方法はある?
一意なidの昇順なら、WHERE id > 最後に取得したid ORDER BY id LIMIT 10のように続きから取る方法があるよ。キーセット方式とも呼ばれる。索引や検索条件を合わせれば遠いページまで飛ばす負担を減らせるけれど、一定速度の保証ではなく、任意のページ番号への直接移動も別に考える必要があるね。
もっと詳しく知りたい人へ
idが一意なら、どんな並べ替えでも最後のidだけ覚えればよい?
並べ替えに使うキーと続きの条件を合わせる必要があります。例えば日時順なら、同じ日時の行を区別する一意なidなども使い、両方を続きの情報として扱います。途中で並べ替えキーの値が変わる場合の扱いも決めましょう。LIMIT/OFFSETや代替構文の対応はDBごとに確認してください。
まとめ:ざっくりこれだけ覚えればOK!
「LIMIT / OFFSET」って出てきたら「最大何行返すか・先頭から何行飛ばすか」と思えばだいたいOK!
📖 おまけ:英語の意味
「LIMIT / OFFSET」 = 制限 / オフセット(ずらし)
💬 limit(制限)で件数を制限し、offset(ずらし)で開始位置をずらすという意味だよ