タイトルまで書いたけど面倒になったんでやめた。
% seq 1000000 > aho.out
mysql> create table aho (id int, col1 int default null, col2 int default null, primary key (id), key (col1)); mysql> load data local infile '/home/ichii386/aho.out' into table aho (id);
col1 が論理削除フラグだと思ってください。
mysql> select sql_no_cache * from aho where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null; +----+------+------+ | id | col1 | col2 | +----+------+------+ | 1 | NULL | NULL | | 2 | NULL | NULL | | 3 | NULL | NULL | | 4 | NULL | NULL | | 5 | NULL | NULL | | 6 | NULL | NULL | | 7 | NULL | NULL | | 8 | NULL | NULL | | 9 | NULL | NULL | | 10 | NULL | NULL | +----+------+------+ 10 rows in set (0.13 sec)
妙に遅い。
mysql> select sql_no_cache * from aho force index (primary) where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null; +----+------+------+ | id | col1 | col2 | +----+------+------+ | 1 | NULL | NULL | | 2 | NULL | NULL | | 3 | NULL | NULL | | 4 | NULL | NULL | | 5 | NULL | NULL | | 6 | NULL | NULL | | 7 | NULL | NULL | | 8 | NULL | NULL | | 9 | NULL | NULL | | 10 | NULL | NULL | +----+------+------+ 10 rows in set (0.00 sec)
期待通り。
"best_access_path": { "considered_access_paths": [ { "access_type": "ref", "index": "col1", "rows": 10, "cost": 12, "chosen": true }, { "access_type": "range", "rows": 8, "cost": 14.02, "chosen": false } ] },
理由は select に col2 が入ってるのに col1 is null な ref を使っちゃうから。
なんで practical にも論理削除はやめてほしい。 orm の都合で index hinting 使えないとかあるあるなんで。