• 【Mysql性能优化系列】MySQL优化WHERE语句18个硬核技巧


    前言

    要让慢SELECT … WHERE查询更快,首先要检查是否可以添加索引。在WHERE子句中使用的列上设置索引,以加快评估、过滤和最终检索结果的速度。本文将学习MySQL对Where语句的优化处理规则。

    WHERE子句优化

    以下示例使用 SELECT语句,但同样适用于DELETE和UPDATE中的WHERE子句 。

    不需要在牺牲可读性的情况下重写sql,因MySQL 会自动进行类似的优化,MySQL执行的一些优化如下:

    1、删除不必要的括号:

       ((a AND b) AND c OR (((a AND b) AND (c AND d))))
    -> (a AND b AND c) OR (a AND b AND c AND d)
    
    • 1
    • 2

    2、恒定折叠:

       (a<b AND b=c) AND a=5
    -> b>5 AND b=c AND a=5
    
    • 1
    • 2

    3、恒定条件去除:

       (b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=7 AND 5=6)
    -> b=5 OR b=6
    
    • 1
    • 2

    4、索引使用的常量表达式只计算一次。

    5、对于没有where 条件的单表 Count(*)直接检索Information_schema库中的统计信息(对 myisam 和 memory表)。

    6、早期检测无效的常量表达式

    MySQL快速发现select语句中不可能成立的where条件并且返回no rows;

    7、如果没有使用group by 或者聚合函数(count(),min().max()),having子句会被合并到where 子句中。

    8、为表连接中的每个表构造一个简洁的 WHERE 语句,以得到更快的 WHERE 计算值并且尽快跳过记录

    9、查询中所有的常量表都会比其他表更早读取。

    一个常量表符合以下几个条件:

    • 空表或只有一行的表。

    • 与在一个 UNIQUE 索引、或一个 PRIMARY KEY 的 WHERE子句一起使用的表,这里所有的索引部分和常数表达式做比较并且索引部分被定义为 NOT NULL。

    • 以下所有表都用作常量表:

    SELECT * FROM t WHERE primary_key=1;
    
    SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
    
    • 1
    • 2
    • 3

    10、MySQL会尽各种可能找到表连接最好的连接方法。 如果在 ORDER BY 和 GROUP BY 子句中的所有字段都来自同一个表的话,那么在连接时这个表就会优先处理

    11、如果有 ORDER BY 子句和一个不同的 GROUP BY 子句,或者如果 ORDER BY 或 GROUP BY 中的字段都来自其他的表而非连接顺序中的第一个表的话,就会创建一个临时表了。

    如下SQL示例:

     desc SELECT
    	a.id 
    FROM
    	`user` a
    	LEFT JOIN account b ON a.id = b.user_id 
    GROUP BY
    	a.id
    	ORDER BY
    	a.id 
    	LIMIT 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

     desc SELECT
    	a.id 
    FROM
    	`user` a
    	LEFT JOIN account b ON a.id = b.user_id 
    GROUP BY
    	b.user_id
    	ORDER BY
    	a.id 
    	LIMIT 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    12、如果使用 SQL_SMALL_RESULT,MySQL就会使用内存临时表了。

    • sql_small_result 告诉MySQL当前select的语句返回的结果集比较小
    • sql_big_result 告诉MySQL当前的select语句返回的结果集比较大

    这两个查询提示直接影响到了对“临时表”使用情况,sql_small_result MySQL使用内存临时表,sql_big_result使用磁盘临时表。

    13、所有的表索引都会查询,最好的情况就是所有的索引都会被用到,除非优化程序认为全表扫描的效率更高。
    数据表扫描是基于判断最好的索引范围超过数据表的30%。 现在,优化程序复杂多了,它基于对一些附加因素的估计,例如表大小,记录总数,I/O块大小,因此就不能根据一个固定的百分比来决定是选择使用索引还是直接扫描数据表

    14、在某些情况下,MySQL可以直接从索引中取得记录而无需查询数据文件。

    如果所有在索引中使用的字段都是数字类型的话,只需要用索引树就能完成查询

    15、每条记录输出之前,那些没有匹配 HAVING 子句的就会被跳过

    16、一些非常快的查询示例:

    SELECT COUNT(*) FROM tbl_name;
    
    SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
    
    SELECT MAX(key_part2) FROM tbl_name
      WHERE key_part1=constant;
    
    SELECT ... FROM tbl_name
      ORDER BY key_part1,key_part2,... LIMIT 10;
    
    SELECT ... FROM tbl_name
      ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    17、MySQL 仅使用索引树解析以下查询,假设索引列是数字:

    SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
    
    SELECT COUNT(*) FROM tbl_name
      WHERE key_part1=val1 AND key_part2=val2;
    
    SELECT MAX(key_part2) FROM tbl_name GROUP BY key_part1;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    18、以下几个查询使用索引来取得经过顺序排序后的记录而无需经过独立的排序步骤

    SELECT ... FROM tbl_name
      ORDER BY key_part1,key_part2,... ;
    
    SELECT ... FROM tbl_name
      ORDER BY key_part1 DESC, key_part2 DESC, ... ;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    点赞 收藏 关注

  • 相关阅读:
    基于粒子群算法的线性规划问题求解matlab程序
    软件项目管理 ——1.3.敏捷项目管理概念
    Python数据结构(顺序表)
    萎凋,是白茶和绿茶的灵魂所在吗?代谢组学给你答案!
    分布式事务简介(seata)
    uView实现全屏选项卡
    Redis源码与设计剖析 -- 10.列表对象
    处理普通用户安装启动mysql报Can‘t find error-message file‘usrsharemysqlerrmsg.sys‘ 问题
    80型泵支架零件制造工艺设计及夹具设计仿真
    浅析三维模型3DTile格式轻量化处理常见问题与处理措施
  • 原文地址:https://blog.csdn.net/qq_35764295/article/details/126890632