カーソルベースのWebナビゲーションをしましたが、なぜ重複データをキャプチャしますか?
問題の背景
データをダウンロードする際、最新順でダウンロードすることにします.
オフセット:
そこでカーソル方式を採用した.
カーソル方式でページング方式で次のコードを実現し、エラーが発生しました.
クエリリクエストの最後のidは7であり、7以降にインポートする必要があります.
データは2,1であり,実際には6,5,4,3,2,1番idをクエリした.どこが問題ですか.
まずはハーモニーを見てみましょう!
@GetMapping
public SeriesSubscribeList.Response getSeriesList(
@RequestParam(required = false) Long lastSeriesId,
@RequestParam @Positive Integer size,
@RequestParam(required = false, defaultValue = "ALL") Category[] categories
) {
return this.seriesService.getSeriesList(lastSeriesId, size, List.of(categories));
}
public SeriesSubscribeList.Response getSeriesList(
Long lastSeriesId,
Integer size
) {
PageRequest cursorPageable = PageRequest.of(
0,
size,
Sort.by(Direction.DESC, "createdAt", "id")
);
return new SeriesSubscribeList.Response((
(lastSeriesId == null) ? this.seriesRepository.findAll(cursorPageable)
: this.seriesRepository.findByIdLessThan(lastSeriesId, cursorPageable)
)
}
List<Series> findByIdLessThan(
Long id,
Pageable pageable
);
コードを表示します.最初のページに入ると最後のidが分からないのでnullをリクエストします.
createdAtは、DESCソート後idが空のためfindAllにデータをインポートします.(実際には、この部分はオフセットでページを分割するのと同じです.)
次に、最後のid値に基づいてfindByIdLessthanにデータをインポートします.primary keyはインデックスであるため、データベースからデータを最初からスキャンする必要がなく、id値に直接アクセスできます.最後のidより小さいidをリクエストのsizeとしてインポートします.コードに異常はないと判断します.
では、データベース・シリーズのテーブルを見てみましょう.
表には以下のデータが含まれており,id 7以降は2,1回のみである.
なぜ6 5 4 3がクリック率になるのでしょうか?
ここに変なところがあります.
idはシリーズ発行の時間順にインクリメントされるため、create atでソートする場合、id値もDESCソートと同じであるべきであると考えられる.
期待されるシーンはidが6,5,4,3,2,1に並べ替えられ,idが6,5,4,3,7,2,1に並べ替えられるのが見られる.
私はこの点をよく考えた.
現在のデータから
まず、createdAtデータが予想通りに入らない理由を理解しました.
原因は.
どうやってこの問題を解決しますか?簡単に思いつく方法は.
ローカル環境とサーバ環境では、この前提がいつでも破られる可能性があると考えています.
さらにidはauto incrementポリシーではなくuuidポリシーである.
カーソルはidではなく、他のデータかもしれないので対応できません.
では、idの順番にかかわらず、自分の意思でidを導入したい場合は、どうすればいいのでしょうか.
最後のidリクエストが11であれば、次のデータは10、9、8、6、5、4、37、3......クエリーされるべきです.
10-1番のデータをどのように照会しますか?
(atが作成され、id DESCがソートされました)
クエリーを考えてみると、以下のようになります.
SELECT * FROM table_name
WHERE created_at < "2021-12-12 07:58:15"
OR (
create_at = "2021-12-12 07:58:15"
and id < 11
)
したがって、2021-12-1207:58:15未満のデータを最初に取得すると、重複する可能性があります.2021-12-1207:58:15、idが11未満のデータを入力すると、所望の結果が得られる.
図では、1番領域と4番領域がクエリーが必要なオブジェクトになります.
Reference
この問題について(カーソルベースのWebナビゲーションをしましたが、なぜ重複データをキャプチャしますか?), 我々は、より多くの情報をここで見つけました https://velog.io/@heehee/커서-기반-페이지네이션을-했는데-왜-중복데이터를-긁어오니テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol