/ 一定行数に届かない大量更新」があった時が一番ズレる ‐ 演算は基本的に構ってくれない INT型で桁あふれが発生しない範囲なら、 id - 1 = 0 ⇔ id = 1 … ‐ DATETIME型で桁あふれが発生しない範囲なら、 ORDER BY created_at と ORDER BY created_at + INTERVAL 1 DAY は同じ順番になるはず… ‐ 6/35
= ? ‐ ある偏りについてオプティマイザが同じ実行計画を選ぶとは限らない ex. SELECT * FROM 住民 WHERE 都道府県 = '東京' ORDER BY birthday DESC LIMIT 10 万 vs. SELECT * FROM 住民 WHERE 都道府県 = '鳥取' ORDER BY birthday DESC LIMIT 10万 たぶん東京はORDER BYを狙った方が速くて、鳥取はWHEREを狙った方が速い(2020年の鳥取の人口は全国の0.4%らしい) 都道府県の人口一覧 - Wikipedia ‐ ex. SELECT * FROM 住民 WHERE 都道府県 = '東京' ORDER BY birthday DESC LIMIT 10 vs. SELECT * FROM 住民 WHERE 都道府県 = '東京' ORDER BY birthday DESC LIMIT 1億 LIMIT 1億だと日本総人口にかなり近いので全件フェッチの実行計画を選ぶが、LIMITの早抜けが効かないのでORDER BY狙いの キーは高速化に寄与できない ‐ だが、偏りに気が付かずにオプティマイザが実行計画を選んでしまうことはある 9/35
? AND registered BETWEEN ? AND ? + INTERVAL 1 MONTH; SELECT * FROM post WHERE user_id = ? AND registered BETWEEN ? AND ? + INTERVAL 1 MONTH O RDER BY registered LIMIT 100 FOR UPDATE; 16/35
みたいなまたいだものも本来 はあるけれども ‐ mysql> SELECT DATE_FORMAT(registered, '%Y%m') AS yyyymm, COUNT(*) FROM post GROUP BY yyyymm ORDER BY COUNT(*) ASC LI MIT 3; +--------+----------+ | yyyymm | COUNT(*) | +--------+----------+ | 200302 | 28 | | 200102 | 28 | | 200202 | 28 | +--------+----------+ 3 rows in set (0.72 sec) mysql> SELECT DATE_FORMAT(registered, '%Y%m') AS yyyymm, COUNT(*) FROM post GROUP BY yyyymm ORDER BY COUNT(*) DESC LIMIT 3; +--------+----------+ | yyyymm | COUNT(*) | +--------+----------+ | 202205 | 91847 | | 200005 | 31 | | 200003 | 31 | +--------+----------+ 3 rows in set (0.70 sec) 18/35
registered BETWEEN ? AND ? + INTERVAL 1 MONTH; SELECT * FROM post WHERE user_id = ? AND registered BETWEEN ? AND ? + INTERVAL 1 MONTH O RDER BY registered LIMIT ? FOR UPDATE; DELETE FROM post WHERE post_id IN (?, ?, .., ?); 31/35