MySQL 索引选择原则分析(示例库)
2015-10-18 00:00
701 查看
摘要: 对不同查询条件分析索引选择情况
目的
数据库中很重要的设计一部分,莫过于索引了。B+树索引是MySQL中设计的索引。B+树索引是基于B+树基础发展而来的。
前面文章MySQL 索引选择原则分析(一)已经对索引做进一步分析。但是实践比较少,只是根据理论做了部分分析,下面对MySQL自己推出的测试数据库及数据做一些SQL的分析。
MySQL示例库下载:
http://pan.baidu.com/s/1ntxmgXV
一:全列匹配
当按照索引中所有列进行精确匹配("="或"IN")时,索引可以被用到。注:理论上索引对顺序是敏感的,但是由于MySQL的查询优化器会自动调整where语句的条件顺序以使用适合的索引,因此前面2条SQL的查询计划是一样的。
二:最左前缀匹配
SQL查询计划可以看出,key用的是PRIMARY索引,但是key_len为4,说明只用了索引第一列。当查询条件精确匹配索引的左边连续一个或几个列时,如<emp_no>或<emp_no,title,from_date>,所以可以被用到,但是只能用到一部分,即where条件所组成的最左前缀。
三:查询条件用到了索引中列的精确匹配,但是中间某个条件未提供
此时查询计划与(二)相同,因为title未提供,所以查询只用到了索引的第一列,而from_date虽然也在索引中,但是由于title不存在而无法和左前缀连接,因此需要对结果进行扫描过滤from_date。
四:查询条件没有指定索引第一列
由于不是最左前缀,所以查询计划使用的是全表扫描。
五:匹配某列的前缀字符串
根据查询计划第一句SQL,type是range,key_len为156,使用了索引的第一列及第二列。
第二剧SQL,查询计划与(二)相同,也就使用了索引的第一列。所以LIKE时候也可以根据具体情况来进行优化的。
六:范围查询
第一句SQL查询计划,type为range,key_len为4,使用了索引的第一列。第二句SQL查询计划,可以看出与第一句是一样的。因此可以看出,范围列可以用到索引,但是范围列后面的列无法用到索引。
第三句SQL查询计划,type为range,key_len为159,也就是使用了索引的所有列。IN使用的是值匹配。
第四句SQL查询计划,type为range,key_len为159,也就是使用了索引的所有列。所以作用于emp_no上的"BETWEEN"实际上相当于"IN",也就是值匹配。
MySQL的查询计划根据type可以无法区分范围索引和多值匹配,因为都是range。因此3、4句SQL才会都用到索引的所有列。
七:查询条件中含有函数或表达式
第一句SQL查看查询计划,发现key_len为4,也就是使用了索引中的第一列。因此查询条件中包含函数或表达式,则MySQL不会为这列使用索引。
第二句SQL查看查询计划,type为ALL,也就是全表扫描,MySQL没有使用索引,MySQL的优化器没有自动的优化常量表达式。
第三句SQL查看查询计划,明显使用了索引的第一列,因此编写SQL时,常量计算尽量放到右边,左边尽量少用表达式。
目的
数据库中很重要的设计一部分,莫过于索引了。B+树索引是MySQL中设计的索引。B+树索引是基于B+树基础发展而来的。
前面文章MySQL 索引选择原则分析(一)已经对索引做进一步分析。但是实践比较少,只是根据理论做了部分分析,下面对MySQL自己推出的测试数据库及数据做一些SQL的分析。
MySQL示例库下载:
http://pan.baidu.com/s/1ntxmgXV
一:全列匹配
SELECT * FROM titles WHERE emp_no='10001' AND title='Senior Engineer' AND from_date='1986-06-26'; SELECT * FROM titles WHERE from_date='1986-06-26' AND emp_no='10001' AND title='Senior Engineer';
当按照索引中所有列进行精确匹配("="或"IN")时,索引可以被用到。注:理论上索引对顺序是敏感的,但是由于MySQL的查询优化器会自动调整where语句的条件顺序以使用适合的索引,因此前面2条SQL的查询计划是一样的。
二:最左前缀匹配
SELECT * FROM titles WHERE emp_no='10001';
SQL查询计划可以看出,key用的是PRIMARY索引,但是key_len为4,说明只用了索引第一列。当查询条件精确匹配索引的左边连续一个或几个列时,如<emp_no>或<emp_no,title,from_date>,所以可以被用到,但是只能用到一部分,即where条件所组成的最左前缀。
三:查询条件用到了索引中列的精确匹配,但是中间某个条件未提供
SELECT * FROM titles WHERE emp_no='10001' AND from_date='1986-06-26';
此时查询计划与(二)相同,因为title未提供,所以查询只用到了索引的第一列,而from_date虽然也在索引中,但是由于title不存在而无法和左前缀连接,因此需要对结果进行扫描过滤from_date。
四:查询条件没有指定索引第一列
SELECT * FROM titles WHERE title='Senior Engineer'; SELECT * FROM titles WHERE from_date='1986-06-26';
由于不是最左前缀,所以查询计划使用的是全表扫描。
五:匹配某列的前缀字符串
SELECT * FROM titles WHERE emp_no='10001' AND title LIKE 'Senior%'; SELECT * FROM titles WHERE emp_no='10001' AND title LIKE '%Senior%';
根据查询计划第一句SQL,type是range,key_len为156,使用了索引的第一列及第二列。
第二剧SQL,查询计划与(二)相同,也就使用了索引的第一列。所以LIKE时候也可以根据具体情况来进行优化的。
六:范围查询
SELECT * FROM titles WHERE emp_no < '10010' AND title='Senior Engineer'; SELECT * FROM titles WHERE emp_no < '10010' AND title='Senior Engineer' AND from_date BETWEEN '1986-01-01' AND '1986-12-31'; SELECT * FROM titles WHERE emp_no IN ('10001','10002','10003','10004','10005','10006','10007','10008', '10009') AND title='Senior Engineer' AND from_date BETWEEN '1986-01-01' AND '1986-12-31'; SELECT * FROM titles WHERE emp_no BETWEEN '10000' AND '10009' AND title='Senior Engineer' AND from_date BETWEEN '1986-01-01' AND '1986-12-31';
第一句SQL查询计划,type为range,key_len为4,使用了索引的第一列。第二句SQL查询计划,可以看出与第一句是一样的。因此可以看出,范围列可以用到索引,但是范围列后面的列无法用到索引。
第三句SQL查询计划,type为range,key_len为159,也就是使用了索引的所有列。IN使用的是值匹配。
第四句SQL查询计划,type为range,key_len为159,也就是使用了索引的所有列。所以作用于emp_no上的"BETWEEN"实际上相当于"IN",也就是值匹配。
MySQL的查询计划根据type可以无法区分范围索引和多值匹配,因为都是range。因此3、4句SQL才会都用到索引的所有列。
七:查询条件中含有函数或表达式
SELECT * FROM titles WHERE emp_no='10001' AND LEFT(title, 6)='Senior'; SELECT * FROM titles WHERE emp_no - 1='10000'; SELECT * FROM titles WHERE emp_no=10000 + 1;
第一句SQL查看查询计划,发现key_len为4,也就是使用了索引中的第一列。因此查询条件中包含函数或表达式,则MySQL不会为这列使用索引。
第二句SQL查看查询计划,type为ALL,也就是全表扫描,MySQL没有使用索引,MySQL的优化器没有自动的优化常量表达式。
第三句SQL查看查询计划,明显使用了索引的第一列,因此编写SQL时,常量计算尽量放到右边,左边尽量少用表达式。
相关文章推荐
- MySQL 索引选择性与前缀索引(示例库)
- Mysql 比较有用的sql命令
- 优化MySQL,还是使用缓存?
- MySQL批量SQL插入性能优化
- MySQL不插入重复数据与删除重复数据
- Mysql中 表数据 和 表结构 的复制语句
- MySQL数据库基准压力测试工具之MySQLSlap使用实例
- MySQL-5.6.13免安装版配置方法以及启动错误
- mysql错误
- 13个MySQL数据库的实用SQL小技巧
- MySQL数据库常用命令大全
- mysql-分区
- MySQL数据优化
- windows下mysql每天定时备份数据库几种方法
- MySQL数据库如何导入导出(备份还原)
- MySql-解决中文乱码问题
- MySQL 的 RowNum 实现(排行榜计算用户排名)
- [实战]MVC5+EF6+MySql企业网盘实战(5)——页面模板
- 查看和修改mysql5.6端口
- Mysql删除所有表不删除数据库方法