Mysql中SQL那些事儿-1

2018/12/20 10:21
阅读数 66

一、SQL语句优化思路:

  1. 把一个大的不使用索引的SQL语句,按照功能进行拆分;
  2. 将长的SQL语句没法使用索引的,经量修改为多个短的SQL使用索引;
  3. SQL中经量避免使用like(特别是 LIKE "%XXX"这种)、OR、!=、<>、in | not in、is null | is not null等

二、SQL中会导致不走索引的情况:

  1.  有应用于谓词的函数,查询中携带函数计算;
  2. 数据类型不匹配,数据库会做隐士数据类型转换;
  3. 列可能包含空值,因为索引中不允许存在空值;
  4. 使用索引实际上比不使用索引更慢,比如表数据较少、列上缺少唯一值的;

三、示例:

-- 不会使用索引,因为所有索引列参与了计算 
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 则不走索引; 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部