MySQL 如何正确的使用索引( 四 )

上面id的值跨度太大,1所在的页和200万所在页中间有很多页需要读取,所以比较慢 。
所以使用between and的时候,区间跨度不要太大 。
in的检索
in方式检索数据,我们还是经常用的 。
平时我们做项目的时候,建议少用表连接,比如电商中需要查询订单的信息和订单中商品的名称,可以先查询查询订单表,然后订单表中取出商品的id列表,采用in的方式到商品表检索商品信息,由于商品id是商品表的主键,所以检索速度还是比较快的 。
通过id在400万数据中检索100条数据,看看效果:
mysql> select * from test1 a where a.id in (100000, 100001, 100002, 100003, 100004, 100005, 100006, 100007, 100008, 100009, 100010, 100011, 100012, 100013, 100014, 100015, 100016, 100017, 100018, 100019, 100020, 100021, 100022, 100023, 100024, 100025, 100026, 100027, 100028, 100029, 100030, 100031, 100032, 100033, 100034, 100035, 100036, 100037, 100038, 100039, 100040, 100041, 100042, 100043, 100044, 100045, 100046, 100047, 100048, 100049, 100050, 100051, 100052, 100053, 100054, 100055, 100056, 100057, 100058, 100059, 100060, 100061, 100062, 100063, 100064, 100065, 100066, 100067, 100068, 100069, 100070, 100071, 100072, 100073, 100074, 100075, 100076, 100077, 100078, 100079, 100080, 100081, 100082, 100083, 100084, 100085, 100086, 100087, 100088, 100089, 100090, 100091, 100092, 100093, 100094, 100095, 100096, 100097, 100098, 100099);+--------+----------------+-----+------------------------+| id | name | sex | email |+--------+----------------+-----+------------------------+| 100000 | javacode100000 | 2 | javacode100000@163.com || 100001 | javacode100001 | 1 | javacode100001@163.com || 100002 | javacode100002 | 2 | javacode100002@163.com |.......| 100099 | javacode100099 | 1 | javacode100099@163.com |+--------+----------------+-----+------------------------+100 rows in set (0.00 sec)
耗时不到1毫秒,还是相当快的 。
这个相当于多个分解为多个唯一记录检索,然后将记录合并 。
多个索引时查询如何走?
我们在name、sex两个字段上分别建个索引
mysql> create index idx1 on test1(name);Query OK, 0 rows affected (13.50 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> create index idx2 on test1(sex);Query OK, 0 rows affected (6.77 sec)Records: 0 Duplicates: 0 Warnings: 0看一下查询:
mysql> select * from test1 where name='javacode3500000' and sex=2;+---------+-----------------+-----+-------------------------+| id | name | sex | email |+---------+-----------------+-----+-------------------------+| 3500000 | javacode3500000 | 2 | javacode3500000@163.com |+---------+-----------------+-----+-------------------------+1 row in set (0.00 sec)
上面查询速度很快,name和sex上各有一个索引,觉得上面走哪个索引?
有人说name位于where第一个,所以走的是name字段所在的索引,过程可以解释为这样:
走name所在的索引找到javacode3500000对应的所有记录
遍历记录过滤出sex=2的值
我们看一下name='javacode3500000'检索速度,确实很快,如下:
mysql> select * from test1 where name='javacode3500000';+---------+-----------------+-----+-------------------------+| id | name | sex | email |+---------+-----------------+-----+-------------------------+| 3500000 | javacode3500000 | 2 | javacode3500000@163.com |+---------+-----------------+-----+-------------------------+1 row in set (0.00 sec)走name索引,然后再过滤,确实可以,速度也很快,果真和where后字段顺序有关么?我们把name和sex的顺序对调一下,如下:
mysql> select * from test1 where sex=2 and name='javacode3500000';+---------+-----------------+-----+-------------------------+| id | name | sex | email |+---------+-----------------+-----+-------------------------+| 3500000 | javacode3500000 | 2 | javacode3500000@163.com |+---------+-----------------+-----+-------------------------+1 row in set (0.00 sec)速度还是很快,这次是不是先走sex索引检索出数据,然后再过滤name呢?我们先来看一下sex=2查询速度:
mysql> select count(id) from test1 where sex=2;+-----------+| count(id) |+-----------+| 2000000 |+-----------+1 row in set (0.36 sec)看上面,查询耗时360毫秒,200万数据,如果走sex肯定是不行的 。
我们使用explain来看一下:
mysql> explain select * from test1 where sex=2 and name='javacode3500000';+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+| 1 | SIMPLE | test1 | NULL | ref | idx1,idx2 | idx1 | 62 | const | 1 | 50.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+1 row in set, 1 warning (0.00 sec)


推荐阅读