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

目的sql

数据库中很重要的设计一部分,莫过于索引了。B+树索引是MySQL中设计的索引。B+树索引是基于B+树基础发展而来的。数据库

前面文章MySQL 索引选择原则分析(一)已经对索引作进一步分析。可是实践比较少,只是根据理论作了部分分析,下面对MySQL本身推出的测试数据库及数据作一些SQL的分析。函数

MySQL示例库下载:测试

http://pan.baidu.com/s/1ntxmgXV优化

一:全列匹配
spa

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的查询计划是同样的。
.net

二:最左前缀匹配
设计

SELECT * FROM titles WHERE emp_no='10001';

SQL查询计划能够看出,key用的是PRIMARY索引,可是key_len为4,说明只用了索引第一列。当查询条件精确匹配索引的左边连续一个或几个列时,如<emp_no>或<emp_no,title,from_date>,因此能够被用到,可是只能用到一部分,即where条件所组成的最左前缀。
code

三:查询条件用到了索引中列的精确匹配,可是中间某个条件未提供
orm

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。所以三、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时,常量计算尽可能放到右边,左边尽可能少用表达式。

相关文章
相关标签/搜索