理想的索引:
- 相对于写操作来说,表查询很频繁的表建立索引
- 字段区分度高
- 长度小(合适的长度,不是越小越好)
- 尽量能够覆盖常用字段
这些条件综合起来才能够达到最优索引,本次我们着重聊一下建立合适长度的索引,索引的长度直接影响索引文件的大小,因此会影响增删改查的速度
给字符类型的字段设置长度字段查询时区分度要高,如果字段只是设置了一个那么回查询很多相似的匹配度不高,长度要恰到好处,否则太长索引文件就会大,因此
要在区分度和长度上做一个平衡。
1.先来看一下没设置索引的查询
mysql> explain select id,title from b2b_goods where title="测试商品";
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | b2b_goods | ALL | NULL | NULL | NULL | NULL | 5061 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
总结:发现该语句没有使用到索引,扫描了5061条数据
2.给title字段创建索引
mysql> alter table b2b_goods add index index_title(`title`);
Query OK, 0 rows affected (0.19 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select id,title from b2b_goods where title="测试商品";
+----+-------------+-----------+------+---------------+-------------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+-------------+---------+-------+------+--------------------------+
| 1 | SIMPLE | b2b_goods | ref | index_title | index_title | 150 | const | 1 | Using where; Using index |
+----+-------------+-----------+------+---------------+-------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
总结:发现该语句扫描条数降低了成了一条,说明是对的,但发现索引长度(key_len)过长这样当更新时是比较占内存的。
3.设置区分度高的并且长度适合的索引
习惯的算法:
select count(distinct left(`title`,num))/count(*) from b2b_goods;
这里num是指截取的长度,实际上也可以发现设置该长度的查询度,比例越大说明越良好
(1).设置6个长度
mysql> select count(distinct left(`title`,6))/count(*) from b2b_goods;
+------------------------------------------+
| count(distinct left(`title`,6))/count(*) |
+------------------------------------------+
| 0.7718 |
+------------------------------------------+
1 row in set (0.01 sec)
(2).设置13个长度
mysql> select count(distinct left(`title`,13))/count(*) from b2b_goods;
+-------------------------------------------+
| count(distinct left(`title`,13))/count(*) |
+-------------------------------------------+
| 0.8288 |
+-------------------------------------------+
1 row in set (0.01 sec)
(3).设置25个长度
mysql> select count(distinct left(`title`,25))/count(*) from b2b_goods;
+-------------------------------------------+
| count(distinct left(`title`,25))/count(*) |
+-------------------------------------------+
| 0.8562 |
+-------------------------------------------+
1 row in set (0.01 sec)
(4).设置30个长度
mysql> select count(distinct left(`title`,30))/count(*) from b2b_goods;
+-------------------------------------------+
| count(distinct left(`title`,30))/count(*) |
+-------------------------------------------+
| 0.8573 |
+-------------------------------------------+
1 row in set (0.01 sec)
(5).设置35个长度
mysql> select count(distinct left(`title`,35))/count(*) from b2b_goods;
+-------------------------------------------+
| count(distinct left(`title`,35))/count(*) |
+-------------------------------------------+
| 0.8573 |
+-------------------------------------------+
1 row in set (0.01 sec)
总结:发现设置字段的长度刚开始越来越大的时候匹配度高,到一定值变化就区域平缓,发现截取30个和35个没什么区分,综上所述并保持适当的长度
我们创建一个长度为25的索引
4.创建区分度高长度适中的索引
alter table b2b_goods drop index index_title;
alter table b2b_goods add index index_title(`title`(25));
mysql> explain select id,title from b2b_goods where title="测试商品";
+----+-------------+-----------+------+---------------+-------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+-------------+---------+-------+------+-------------+
| 1 | SIMPLE | b2b_goods | ref | index_title | index_title | 75 | const | 1 | Using where |
+----+-------------+-----------+------+---------------+-------------+---------+-------+------+-------------+
1 row in set (0.00 sec)
总结:跟之前没有设置长度的比较key_len由150减少为75,扫描条数依然是一条,相比之下这个长度是优秀的索引长度。