web-dev-qa-db-ja.com

MySQL-UUID / created_atカーソルベースのページネーション?

大規模なデータセットの場合、OFFSETを使用したページ付けは速度が遅く、ページ付けの最適な方法ではないことがわかっています。ページ付けを行うより優れた方法は、カーソルを使用することです。これは行の一意の識別子であり、最後のカーソル位置から最後に中断したところからページ付けを継続する場所がわかります。

カーソルが自動インクリメントid値である場合、実装はかなり簡単です。

SELECT * FROM users
WHERE id <= %cursor // cursor is the auto incrementing id, ex. 100000
ORDER BY id DESC
LIMIT %limit

確信が持てないのは、自動インクリメントするidカーソルの代わりに、カーソルの一意の順次識別子がテーブル行のuuidcreated_atだけである場合です。

確かにuuidに基づいてクエリを実行してcreated_atを取得し、<= created_atであるすべてのusersを選択することができますが、問題は、 usersテーブルの同じcreated_atタイムスタンプ? uuid/created_atカーソルの組み合わせに基づいてuserstableにクエリを実行し、正しいデータセットを取得する方法を教えてください(自動インクリメントidを使用しているかのように)?繰り返しますが、created_atは重複する可能性があるため、唯一の一意のフィールドはuuidですが、それらの組み合わせは行ごとに一意になります。

3
Wonka

私はあなたが尋ねたものに答えますが、最初に、なぜあなたがそれをしたいのか、私には理解できないと言っておきます。自動増分IDは、このタスクに非常に適しています。ただし、並べ替えにIDに依存することは悪い習慣であるため、timestamp列も使用することは適切です。どうして?たとえば、Galeraクラスターを使用していてフェイルオーバーが発生している場合など、その順序が時系列ではない場合があるためです。

要求したことを行うには、まずこのインデックスを作成します。

ALTER TABLE users
    ADD INDEX idx_created_at_uuid (created_at, uuid);

列の順序は重要です。逆にすると、インデックスは役に立ちません。

次のようなクエリを実行するだけです。

SELECT some_columns
    FROM users
    WHERE created_at <= x AND uuid = y
    ORDER BY created_at DESC;

uuidは、created_atが一意でないためにのみ必要です。 created_atは最初の列ではありません。MySQLはすべての行を読み取り、それらをソートするためにそれらを一時テーブル(メモリ内またはディスク上の可能性があります)にコピーする必要があります。

IDを使用する場合は、上記のスニペットをそのまま使用しますが、uuididに置き換えます。

3
WHERE   created_at <= x
  AND ( created_at < x OR uuid < y )
ORDER BY created_at DESC,
         uuid       DESC

またはこれと同等のもの:

WHERE (     created_at < x
       OR ( created_at = x OR uuid < y )
      )
ORDER BY created_at DESC,
         uuid       DESC

この手法は、最初の列(created_at)が重複する可能性があり、2番目の列が一意である(uuidまたはid)列のペアに対して機能します。

そしてこれは必須です:

INDEX(created_at, uuid)

WHEREの両方の部分はDESCであることに注意してください。 ASCDESCを混在させると、INDEXの使いやすさが損なわれます。 (MySQL 8.0はそれを回避できます。)

また、これは、created_atが重複しているときに行の順序を気にしないことを前提としていますが、consistentが必要であることにも注意してください。注文。 uuidはランダムに見えますが、一貫性があることに注意してください。そうは言っても、id(Galeraの有無にかかわらず)とuuidは同じように機能します。

(UUIDは吸うが、それは 別の議論 である)

OFFSET を使用しない改ページの詳細。

4
Rick James