一、SQL语句优化思路:
- 把一个大的不使用索引的SQL语句,按照功能进行拆分;
- 将长的SQL语句没法使用索引的,经量修改为多个短的SQL使用索引;
- SQL中经量避免使用like(特别是 LIKE "%XXX"这种)、OR、!=、<>、in | not in、is null | is not null等
二、SQL中会导致不走索引的情况:
- 有应用于谓词的函数,查询中携带函数计算;
- 数据类型不匹配,数据库会做隐士数据类型转换;
- 列可能包含空值,因为索引中不允许存在空值;
- 使用索引实际上比不使用索引更慢,比如表数据较少、列上缺少唯一值的;
三、示例:
-- 不会使用索引,因为所有索引列参与了计算
SELECT `sname` FROM `stu` WHERE `age`+10=30;
-- 不会使用索引,因为使用了函数运算,原理与上面相同
SELECT `sname` FROM `stu` WHERE LEFT(`date`,4) <1990;
-- 走索引
SELECT * FROM `houdunwang` WHERE `uname` LIKE'后盾%';
-- 不走索引
SELECT * FROM `houdunwang` WHERE `uname` LIKE "%后盾%";
-- 字符串与数字比较不使用索引;
CREATE TABLE `a` (`a` char(10));
-- 走索引
EXPLAIN SELECT * FROM `a` WHERE `a`="1";
-- 不走索引,同样也是使用了隐试类型转换函数
EXPLAIN SELECT * FROM `a` WHERE `a` = 1;
注:在工作中,我们用于捕捉性能问题最常用的就是打开慢查询,定位执行效率差的SQL,那么当我们定位到一个SQL以后还不算完事,我们还需要知道该SQL的执行计划,比如是全表扫描,还是索引扫描,这些都需要通过EXPLAIN去完成。EXPLAIN命令是查看优化器如何决定执行查询的主要方法。可以帮助我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。需要注意的是,生成的QEP并不确定,它可能会根据很多因素发生改变。MySQL不会将一个QEP和某个给定查询绑定,QEP将由SQL语句每次执行时的实际情况确定,即便使用存储过程也是如此。尽管在存储过程中SQL语句都是预先解析过的,但QEP仍然会在每次调用存储过程的时候才被确定。
组合索引相关:
-- 创建测试表:
CREATE TABLE `myIndex` (
`i_testID` INT NOT NULL AUTO_INCREMENT,
`vc_Name` VARCHAR(50) NOT NULL,
`vc_City` VARCHAR(50) NOT NULL,
`i_Age` INT NOT NULL,
`i_SchoolID` INT NOT NULL,
PRIMARY KEY (`i_testID`)
);
-- 假设表内已有10000条数据,在这 10000 条记录里面 散乱地分布了 5 条 vc_Name=”erquan” 的记录,只不过 city,age,school 的组合各不相同
查询语句:
-- 关联搜索;
SELECT `i_testID` FROM `myIndex` WHERE `vc_Name`='erquan' AND `vc_City`='上海' AND `i_Age`=28;
1、考虑单索引:
在 vc_Name 列上建立了索引。执行 T-SQL 时,MYSQL 很快将目标锁定在了 vc_Name=erquan 的 5 条记录上,取出来放到一中间结果集。在这个结果集里,先排除掉 vc_City 不等于”郑州”的记录,再排除 i_Age 不等于 25 的记录,最后筛选出唯一的符合条件的记录。虽然在 vc_Name 上建立了索引,查询时MYSQL不用扫描整张表,效率有所提高,但离我们的要求还有一定的距离。同样的,在 vc_City 和 i_Age 分别建立的MySQL单列索引的效率相似。
2、为了进一步榨取 MySQL 的效率,就要考虑建立组合索引。就是将 vc_Name,vc_City,i_Age 建到一个索引里:
-- 创建组合索引
ALTER TABLE `myIndex` ADD INDEX `name_city_age` (vc_Name(10),vc_City,i_Age);
3、如果分别在 vc_Name,vc_City,i_Age 上建立单列索引,让该表有 3 个单列索引,查询时和上述的组合索引效率一样吗?答案是大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但 MySQL 只能用到其中的那个它认为似乎是最有效率的单列索引,另外两个是用不到的,也就是说还是一个全表扫描的过程。
4、mysql组合索引“最左前缀”原则,下面这样创建的组合索引,相当于分别创建了单独索引:
- vc_Name,vc_City,i_Age
- vc_Name,vc_City
- vc_Name
-
SELECT * FROM myIndex WHREE vc_Name=”erquan” AND vc_City=”上海”; SELECT * FROM myIndex WHREE vc_Name=”erquan”; SELECT * FROM myIndex WHREE i_Age=28 AND vc_City=”上海”; SELECT * FROM myIndex WHREE vc_City=”上海”; name_city_age(vc_Name(10),vc_City,i_Age) 从左到右进行索引,如果没有左前索引Mysql不执行索引查询。
5、如果使用的组合所以 a、b、c。则相等于分别创建a、ab、abc三个索引。如果此时查询条件 是 a and c 则会走索引;如果是查询 b and c 则不走索引;