(この記事は私の blog の http://umezawa.dyndns.info/wordpress/?p=7323 の転載です)
概要
真偽値型(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