MySQLのインデックスの気になる所を確認してみる

CentOSにMySQLとMemcacheのインストールしてみる
MySQLをインストールした状態。

MySQLのインデックスで下記の点が気になったので確認してみる。

・NULL可のカラムでもインデックスが効くのか
・日時(datetime)でもインデックスが効くのか
・不等号でもインデックスが効くのか
・ユニークインデックスでもインデックスとして効くのか

準備

testデータベースで試す。

msyql> use test

大量にレコードを追加するためのテーブルを用意しておく。

mysql> create table tmp (id int NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
mysql>insert into tmp values (), (), (), (), (), (), (), (), (), ();

NULL可のdatetime型のカラムを持つテーブルを作成する。

mysql> create table sample (
  id      int         NOT NULL AUTO_INCREMENT,
  dt      datetime,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

データを10000万件入れる。

mysql> insert into sample (dt)
 select
  FROM_UNIXTIME(t7.id * 1000000 + t6.id * 100000 + t5.id * 10000 + t4.id * 1000 + t3.id * 100 + t2.id * 10 + t1.id - 1111110)
 from tmp t1, tmp t2, tmp t3, tmp t4, tmp t5, tmp t6, tmp t7;

下記のような感じでデータが入る。

mysql> select * from sample limit 10;
+----+---------------------+
| id | dt                  |
+----+---------------------+
|  1 | 1970-01-01 09:00:01 |
|  2 | 1970-01-01 09:00:02 |
|  3 | 1970-01-01 09:00:03 |
|  4 | 1970-01-01 09:00:04 |
|  5 | 1970-01-01 09:00:05 |
|  6 | 1970-01-01 09:00:06 |
|  7 | 1970-01-01 09:00:07 |
|  8 | 1970-01-01 09:00:08 |
|  9 | 1970-01-01 09:00:09 |
| 10 | 1970-01-01 09:00:10 |
+----+---------------------+
mysql> select count(*) from sample;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+

インデックスを設定していない場合

インデックスが無い状態で、日時のカラムを不等号で検索すると、
3秒ほどかかった。

mysql> select count(*) from sample where dt >= '1970-03-01 00:00:00' and dt <= '1970-03-01 23:59:59';
+----------+
| count(*) |
+----------+
|    86400 |
+----------+
1 row in set (2.96 sec)

当然インデックスは有効でない。

mysql> explain select count(*) from sample where dt >= '1970-03-01 00:00:00' and dt <= '1970-03-01 23:59:59';
+----+-------------+--------+------+---------------+------+---------+------+----------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows     | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | sample | ALL  | NULL          | NULL | NULL    | NULL | 10000378 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+----------+-------------+

インデックスを設定した場合

ユニークインデックスを設定する。

mysql> alter table sample add unique (dt);

再度、日時のカラムを不等号で検索すると、
一瞬で終わった。

mysql> select count(*) from sample where dt >= '1970-03-01 00:00:00' and dt <= '1970-03-01 23:59:59';
+----------+
| count(*) |
+----------+
|    86400 |
+----------+
1 row in set (0.03 sec)

インデックスが効いてるのが分かる。

mysql> explain select count(*) from sample where dt >= '1970-03-01 00:00:00' and dt <= '1970-03-01 23:59:59';
+----+-------------+--------+-------+---------------+------+---------+------+--------+--------------------------+
| id | select_type | table  | type  | possible_keys | key  | key_len | ref  | rows   | Extra                    |
+----+-------------+--------+-------+---------------+------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | sample | range | dt            | dt   | 9       | NULL | 201710 | Using where; Using index |
+----+-------------+--------+-------+---------------+------+---------+------+--------+--------------------------+