您的位置:首页 > 数据库 > MySQL

MySQL 索引选择原则分析(示例库)

2015-10-18 00:00 701 查看
摘要: 对不同查询条件分析索引选择情况

目的
数据库中很重要的设计一部分,莫过于索引了。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时,常量计算尽量放到右边,左边尽量少用表达式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: