ページングって?
Webサイトの一覧画面って大概ページングする。
ページングとは、まさに、複数行を1画面に表示して、次のページにまた複数行を表示するようインターフェースのこと。
UIとして、画面を移動したり、画面下部に継ぎ足されたりとかいろんなパターンはあるが、そこは重要ではなく、データ構造としてどう取り出すかというのがポイント。
古くから有る例「limit」
SQLにはlimit句がある
select * from users order by id limit 20,10;
この例では、「21番め移行を10件とってきなさいよ」って命令になる。
10件ずつとってくるのは、一気に10万件とかとってきちゃうと画面のデータがいっぱいになっちゃうから。かならず上限は決める。
Webの一覧画面では、レコード数ではなく「1ページあたりの件数を決めて」「何ページ目からのスターとか」ってことで、UIをつくる。ECサイトの大半はそういう作り。
URLのクエリストリングにp=2
とかpage=2
とかついてるから、いきなりp=10
とかってやれば、いきなり後ろの方のデータを取得できる。
今風のページングは、max_id を取得
limitを使ったページングは、これはこれで、教科書どおりなんだけど、offsetって後ろの方のページになると遅いんですね。じゃぁってことで、イマドキはmax_idをつかう。max_idってのはSQLの用語ではなく、「そのページにある最大のidを覚えておいてそれより小さな件数を取得する」ということ。
Twitterなんかがまさにそうで、そのページのTweetの最大をとっておいて、それより小さなTweetIDを取得するようにしている。
RubyのActiveRecordも、バッチ処理で複数レコードを処理するときには、以下のように、処理したIDの最大を勝手に覚えてくれるので、メモリがあふれることなく、次々と処理をしてくれる。
SELECT `users`.* FROM `users` WHERE (`users`.`id` > 1001) ORDER BY `users`.`id` ASC LIMIT 1000
max_idでページングするデメリット
並び順の種類が2個になっちゃう
「このid以前(以降)何件頂戴」はDBに対してはすごく速いんだけど、並び順が制御できない(idの昇順か降順)。SNSは、新着順が殆どなので、増えていくタイプのIDだと、IDの降順でだいたいこと足りる。だけどSNSのとかだと、必ずしも新着順じゃなくて、オススメ順だとかレビュー数順とかになる。
その場合は、並び順で制御するのではなく、抽出条件として「★3つ以上」とかのUIにするとかで回避。
ランダムなIDは使いづらい
そもそも、IDがオートナンバーで増えつづける方式もそれはそれで古い。オートナンバー方式だとDBが分残しにくいので、UUID的なランダムな文字列を主キーにするというスタイルも出てきている。その場合は時刻で並ばない。そんなわけで、「分散しやすいランダム文字列だけど並び順は時系列」というスタイルの主キーをつかうのがSNSでは多い。
まとめ
SNSなんかは、自由に並び替えたいというニーズよりも、「情報の鮮度」「情報の量」「レスポンスの速さ」が大事なので、絶対max_idの方がいい。