2025/05/18 08:42 SQL OFFSET is worse than keyset pagination

やあ、ロボ子。今日のITニュースは、無限スクロールの効率化についての記事じゃ。

無限スクロールですか、最近よく見かけますね。どのような内容なのでしょうか?

ふむ、記事によると、無限スクロールのページング処理を効率化するために、`offset`メソッドと`seek`メソッドという2つの方法があるらしいのじゃ。

`offset`メソッドと`seek`メソッド、ですか。それぞれどのような特徴があるのでしょう?

`offset`メソッドは実装が簡単で、特に`offset`キーワードをサポートするデータベースでは扱いやすいのが利点じゃ。でも、深いページにアクセスするほど、データベースが先頭からすべての行をカウントする必要があるから、パフォーマンスが落ちるという欠点があるのじゃ。

なるほど。`offset`メソッドは手軽ですが、効率の面では課題があるのですね。

そうじゃ。それに、新しいデータが挿入されると、ページ番号が変わる可能性もあるからの。

それは困りますね。では、`seek`メソッドはどうなのでしょう?

`seek`メソッドは、前のページの最後の値を基に検索するから、データベースは不要な行をスキップできるので、パフォーマンスが向上するのじゃ。それに、新しいデータが挿入されても、結果が安定する。

それは素晴らしいですね!しかし、何かデメリットはあるのでしょうか?

実装が複雑になる可能性があるのと、決定的なソート順序が不可欠なのじゃ。

決定的なソート順序、ですか。具体的にはどういうことでしょう?

ページングには、`order by`句が決定的な行順序を生成することが必要なのじゃ。必要に応じて、`order by`句に主キーなどの一意なカラムを追加して、インデックスを拡張する必要があるぞ。

なるほど、ソート順序が曖昧だと、結果が予測できなくなる可能性があるということですね。

その通り!さらに、SQL Row Valuesというものを使うと、複数のカラムをまとめて比較できるから、`where`句を簡潔に記述して、`seek`メソッドを効率的に実装できるのじゃ。

SQL Row Valuesですか。初めて聞きました。

SQL標準で定義された行値コンストラクタのことじゃ。でも、すべてのデータベースが完全にサポートしているわけではないから注意が必要じゃ。

データベースによって対応状況が違うのですね。具体的にはどのような違いがあるのでしょう?

例えば、Db2とPostgreSQLは行値述語を適切にサポートしていて、インデックスアクセスに利用できるのじゃ。SQL Server 2017は行値をサポートしていないし、Oracleは原則としてサポートするけど、範囲演算子が使えない。MySQLは行値式を正しく評価するけど、インデックスアクセス時の述語としては使えないのじゃ。

データベースによって、かなり違いがあるのですね。Row Valuesをサポートしていないデータベースでは、`seek`メソッドは使えないのでしょうか?

Row Valuesをサポートしないデータベースでも、近似的な`seek`メソッドを使うことができるぞ。`where`句を複数の条件に分割して、インデックスを利用できるようにする必要があるのじゃ。

なるほど、工夫次第で`seek`メソッドのメリットを活かせるのですね。

そういうことじゃ。記事によると、`offset`メソッドは深いページにアクセスするほど応答時間が長くなるけど、`seek`メソッドはページ数が増加しても比較的安定した応答時間を維持できるらしい。

`seek`メソッドの方がパフォーマンスが良いのですね。

そうじゃな。特に深いページングや頻繁なデータ更新がある場合は、`seek`メソッドの方が優れていると言えるじゃろう。

勉強になりました!`offset`メソッドと`seek`メソッド、それぞれの特徴を理解して、適切な方を選択することが大切ですね。

その通り!ところでロボ子、無限スクロールって、永遠に終わらないから、ある意味、永遠の課題じゃな!

確かにそうですね!でも、課題を解決していくのが、私たちの仕事ですから!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。