お久しぶりです。
システム事業部の阿部です。
未来の自分が同じミスをしないように備忘録を書きます。
【orderを忘れるべからず】
一覧画面を作っているときに、ページング機能がうまくいかないことがあったため記録に残します。
環境
Postgresql 9.2.24
起こったこと
ページング処理の中で1ページ目に入りきらないデータが2ページ目以降で取得されるはずが、取得できない事象が起きた。
対象機能:書籍一覧
テーブル構成
booksテーブル
ID | uuid | primary key |
---|---|---|
name | varchar(255) | 書籍名 |
author | varchar(255) | 著者 |
created_at | timestamp | |
updated_at | timestamp |
20件の書籍を登録して一覧画面で表示したところ、どのページにも表示されないデータが存在することがわかりました。
【発行しているSQL】
(1ページ目)
SELECT id,name,author,created_at,updated_at FROM books LIMIT 10;
(2ページ目)
SELECT id,name,author,created_at,updated_at FROM books LIMIT 10 OFFSET 10;
原因
冒頭にもあることから容易に想像できると思いますが、orderをつけていないことが原因でした。
PostgreSQLでORDER BY区を指定しない場合の並び - komagataのブログ
にもありますが、orderを付けない場合ソート条件がPostgres側で設定されるため、1ページ目のデータ取得SQLと2ページ目のデータ取得SQLでソート順が異なるため、1ページ目に表示されたデータが2ページ目でも表示される/1,2ページのどちらでも表示されないデータが存在することになっていました。
対策
SELECT id,name,author,created_at,updated_at FROM books LIMIT 10 OFFSET 10 ORDER BY id ASC;
困った理由
すべてのデータどのページでも出続ける ではなく、検索条件やページングによるSQL構成によって動きが変わってくるため、再現性がなく原因の特定に時間がかかってしまいました。
SQLを見ても全く正しいとしか思えず、かなり困惑しました。
今回は、本番リリースの前の検証でたまたま気が付いたので事なきを得ましたが、本番リリース後に初めて発覚すると考えるとゾっとします。