MEDIA

メディア

  1. TOP
  2. メディア
  3. プログラミング
  4. SQLのOFFSETとは?LIMITとの違い・ページングと性能対策完全解説

SQLのOFFSETとは?LIMITとの違い・ページングと性能対策完全解説

「SQLで2ページ目を取得したい」
「LIMITとOFFSETの違いが曖昧…」
「ページングが不安定になって困っている」
「大きなOFFSETが遅いのはなぜ?」

このような悩みを持つエンジニアは非常に多いです。

OFFSETは“どこから取得するか”を決める機能、LIMITは“何件取得するか”を決める機能です。
しかし実務では、ORDER BYとの関係、性能問題、DB製品ごとの差異まで理解していないと事故につながります。

本記事では以下を網羅的に解説します。

  • OFFSETとLIMITの基本構文
  • ORDER BYとの本質的な関係
  • 正しいページネーション実装
  • よくある落とし穴
  • パフォーマンス問題とキーセットページネーション
  • DB製品ごとの書き方の違い

初心者にも分かりやすく、実務者が納得できる深さで解説します。

OFFSETとLIMITの基本概念

LIMITとは(取得件数を制御する)

LIMITは「返す最大件数」を指定します。

SELECT * FROM users LIMIT 10;

→ 最大10件返す

用途例:

  • 最新1件だけ取得したい
  • 一覧画面は10件ずつ表示したい
  • デバッグ時に少数件だけ確認したい

LIMITはパフォーマンス改善の第一歩です。
不要な大量データ取得を防ぎ、メモリ・通信負荷を抑えます。

OFFSETとは(開始位置を制御する)

OFFSETは「先頭から何行スキップするか」を指定します。

SELECT * FROM users LIMIT 10 OFFSET 20;

→ 21行目から10件取得

OFFSETは0始まりです。

OFFSET値 開始位置
0 1行目
1 2行目
10 11行目

LIMITとOFFSETの違い

機能 役割
LIMIT 取得件数を決める
OFFSET 取得開始位置を決める

この2つを組み合わせて初めて「ページネーション」が成立します。

なぜOFFSETはORDER BYとセットで使うべきなのか

ORDER BYがないと順序は保証されない

RDBMSでは、ORDER BYがなければ返却順は保証されません

参考(公式ドキュメント)
PostgreSQL公式:https://www.postgresql.org/docs/current/queries-order.html
MySQL公式:https://dev.mysql.com/doc/refman/8.0/en/order-by-optimization.html

つまり、

SELECT * FROM users LIMIT 10 OFFSET 10;

は実行のたびに違う結果になる可能性があります。

安定したページングの条件

必ず以下を守る必要があります。

  1. ORDER BYを指定する

  2. 同順位が発生しないよう一意性を担保する

例:

ORDER BY created_at DESC, id DESC

created_atだけでは同時刻が存在します。
主キーでタイブレークすることで安定します。

ページネーション実装の基本

ページ番号からOFFSETを計算する式

OFFSET = (page - 1) × per_page

例:1ページ10件

page OFFSET
1 0
2 10
3 20

実装例(1ページ10件)

SELECT * FROM users ORDER BY id ASC LIMIT 10 OFFSET 20;

→ 3ページ目(21〜30件目)

API設計のベストプラクティス

推奨:

  • page(1始まり)
  • per_page(上限あり)

注意点:

  • per_pageの最大値を制限(例:100)
  • pageが異常値なら補正
  • offsetを直接公開しない

よくある失敗パターン

1. ORDER BYなしでOFFSETを使う

→ ページ間で重複・欠落発生

2. 同順位で並びが不安定

ORDER BY created_at DESC

→ 同時刻データが多いとページ境界が揺れる

3. 更新が頻発するテーブル

ページ閲覧中にINSERTが入るとズレます。

例:

  • 2ページ目閲覧中
  • 先頭に新規データ追加
  • 次ページ取得で重複発生

これはOFFSET方式の構造的弱点です。

なぜ大きなOFFSETは遅くなるのか?

本質的な理由

OFFSET 10000 の場合:
→ DBは最初の10000行を処理してから捨てる

つまり「読み飛ばしコスト」が発生します。

特にORDER BY付きの場合、ソートコストも加算されます。

参考:
PostgreSQL実行計画解説
https://www.postgresql.org/docs/current/using-explain.html

解決策:キーセット(キーベース)ページネーション

キーセット方式とは?

「何行目」ではなく
「どのキー以降」を指定する方式

SQL例

SELECT * FROM users WHERE id > :last_id ORDER BY id ASC LIMIT 10;

特徴:

  • 深いページでも高速
  • 重複・欠落が起きにくい
  • 無限スクロール向き

複合ソートの場合

WHERE (created_at, id) < (:last_created_at, :last_id)

OFFSET方式 vs キーセット方式

項目 OFFSET キーセット
任意ページジャンプ ×
深いページ性能
更新耐性
実装難易度

DB製品ごとの構文差

MySQL / PostgreSQL

LIMIT n OFFSET m

公式:

SQL Server

ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

ORDER BY必須。

公式:https://learn.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql

Oracle

12c以降:

OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

公式:https://docs.oracle.com/en/database/

SQLite

LIMIT 10 OFFSET 10

公式:https://sqlite.org/lang_select.html

実務で必ず確認すべき3点

  1. 任意ページジャンプは必要か?

  2. ORDER BYは一意か?

  3. 深いページアクセスは発生するか?

これを決めずに実装すると後で作り直しになります。

まとめ

本記事の要点

  • LIMITは件数制御
  • OFFSETは開始位置制御
  • 必ずORDER BYとセットで使う
  • 同順位は主キーで確定させる
  • 深いページは遅くなる
  • 更新が多いならキーセット方式を検討

次にやるべきこと

  • 自分のプロジェクトでORDER BYが安定しているか確認する
  • インデックス設計を見直す
  • 深いページアクセスがあるか分析する
  • 必要ならキーセット方式に切り替える

エンジニアとして一段上に進むために

OFFSETを「なんとなく」使っている段階から、
性能・一貫性・UXまで考えられる設計ができる段階へ。

私たちはデータベース設計・パフォーマンス改善・API設計に強いエンジニアチームです。

  • 実行計画を読める
  • インデックス設計を語れる
  • 負荷を見据えた設計ができる

そんな技術志向の仲間を探しています。

もしこの記事を読んで
「もっと深く設計を理解したい」
「パフォーマンス最適化を極めたい」

と感じた方は、ぜひ当社の採用情報もご覧ください。

高度な設計に本気で向き合える環境で、一緒にプロダクトを進化させていきましょう。

学んだSQLを、実務で使えるスキルにしたい方へ

本記事ではSQLの基本的な考え方や使い方を解説しましたが、
「実務で使えるレベルまで身につけたい」と感じた方も多いのではないでしょうか。

SQLは、文法を理解するだけでなく、

  • どんなデータ構造で使われるのか
  • どんなクエリが現場で求められるのか

を意識して学ぶことで、実践力が大きく変わります。

そうした「実務を見据えたSQL学習」を進めたい方には、
完全無料で学べるプログラミングスクール ZeroCode という選択肢もあります。

  • SQLを含むWeb・データベース系スキルを体系的に学べる
  • 未経験者でも実務を意識したカリキュラム
  • 受講料・教材費がかからない完全無料の学習環境
  • 完全オンラインでスキマ学習


ZeroCodeについて詳しく見る

※学習内容や進め方を確認するだけでもOKです

Join us! 未経験からエンジニアに挑戦できる環境で自分の可能性を信じてみよう 採用ページを見る→

記事監修

ドライブライン編集部

[ この記事をシェアする ]

記事一覧へ戻る