【りみっと おふせっと】

LIMIT / OFFSET とは?

最終更新:
💡 順序を決めて、必要な範囲の行を取り出す

LIMITは取得する最大行数、OFFSETは結果の先頭から飛ばす行数を指定するSQLの句。ページ送りでは一意に決まるORDER BYが重要です。大きなOFFSETの負担と、続きのキーから取得する方法も解説します。

📌 このページのポイント
LIMIT/OFFSET:必要な範囲を取り出すORDER BY id LIMIT 5 OFFSET 5全15行の例。idは一意なキー1〜5行目OFFSET 5で飛ばす6〜10行目LIMIT 5で返す11〜15行目今回は範囲外結果内の位置と、idの値は別追加・削除で位置はずれる大きなOFFSETの処理負担にも注意
ORDER BYで順序を決めた結果から、先頭5行を飛ばし最大5行を返す例です。行番号はidではありません。結果が足りなければ指定数より少なくなります。
ひよこ ひよこ
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(ずらし)で開始位置をずらすという意味だよ

参考資料

← 用語集にもどる