8月
10
真偽値型(BIT(1) とか BOOLEAN(TINYINT のエイリアス)のこと)のカラムにインデックスを張っても、手抜きな SQL 文を書くとインデックスを使ってくれないようです。
mysql> CREATE TABLE booltest (
bit1 BIT(1) NOT NULL,
tis TINYINT NOT NULL,
tiu TINYINT UNSIGNED NOT NULL,
val INT NOT NULL,
INDEX (bit1),
INDEX (tis),
INDEX (tiu)
);
(略)
(ランダムなデータをプログラム的につっこむ)
mysql> EXPLAIN SELECT * FROM BOOLTEST WHERE bit1;
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | booltest | NULL | ALL | NULL | NULL | NULL | NULL | 998681 | 50.00 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
mysql> EXPLAIN SELECT * FROM BOOLTEST WHERE bit1 = true;
+----+-------------+----------+------------+------+---------------+------+---------+-------+--------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+-------+--------+----------+-------+
| 1 | SIMPLE | booltest | NULL | ref | bit1 | bit1 | 1 | const | 499340 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+------+---------+-------+--------+----------+-------+
bit1 = true と書かないとインデックスを使ってくれません。TINYINT 型にしてある tis, tiu でも同様です。普通のプログラミング言語なら bit1 が真偽値型なら bit1 と書いたのと bit1 = true と比較演算したのとは全く同じであるはずですが、SQL (MySQL) ではそういう挙動になってくれないようです。ちなみに EXPLAIN を外して実際にクエリしてみた場合、出てくる行は順番も含めて同じです。
まあ、プログラマが勝手に真偽値型だと思ってるだけであって、 TINYINT は数値型だし BIT(1) は値域が限定されている BINARY 型でしかないなので、MySQL はそこまで気を効かせてくれないのかもしれない…
使った環境:
- Ubuntu 18.04 TLS
- MySQL 5.7.27
no comment untill now