mysql查询性能优化

慢查询判定

1.开启慢查询日志记录执行时间超过long_query_time 秒的sql语句
2.通过show processlist命令查看线程执行状态
3.通过explain解析sql了解执行状态

慢查询优化

是否向服务器请求列不必要的数据
  • 查询不需要的记录--- limit
  • 多表关联返回全部列
  • 总是取出全部列
  • 重复IO
是否走索引

建立索引的原则:
1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2.等值查询=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。

4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。

5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

innodb无法使用索引情况:

1.查询条件是表达式一部分或者是函数的参数
2.多列索引不符合最左前缀匹配原则
3.模糊匹配like,“%”不能在第一个位置

查询sql是否合理

一个复杂查询还是一个简单查询
切分查询
分解关联查询

将一个大的查询分解为多个小查询是很有必要的。很多高性能的应用都会对关联查询进行分解,就是可以对每一个表进行一次单表查询,然后将查询结果在应用程序中进行关联,很多场景下这样会更高效

优化表结构

  • 将字段很多的表分解成多个表 (垂直拆分)
  • 表水平拆分(分库分表)
  • 对于需要经常联合查询的表,可以建立中间表以提高查询效率
mysql是否在扫描额外的记录

判断标准

1. 查询响应时间
2. 扫描的行数和返回的行数
3. 访问类型,Explain的 type字段值反映扫描类型






查询执行基础

查询执行路径

客户端/服务器通信

半双工模式---- 任意时刻数据只能单向传输

查询状态

show full processlist --- 显示查询线程执行状态

  • Sleep -- 线程正在等待客户端发送新的请求
  • Query -- 线程正在执行或者正在将结果发送给客户端
  • Locked --

查询缓存

哈希表实现

查询优化处理

sql解析 -- 预处理 -- 优化sql执行计划

查询优化器
  1. 重新定义关联表的顺序
  2. 将外连接转化为内连接
  3. 使用等价变换规则
  4. 优化COUNT() -- MyISAM维护一个变量存放表的行数, MIN() -- 查询列对应B+树索引最左端记录 ,MAX() -- 查询列对应B+树索引最右端记录
  5. 预估并转化为常数表达式
  6. 覆盖索引扫描
  7. 子查询优化
  8. 提前终止查询,如Limit
  9. 等值传播
  10. 列表IN()的比较

Explain

select_type(查询类型)

表示查询的类型

type(访问类型)

重要指标,一般得保证查询至少达到range级别,最好能达到ref

Extra

显示MySQL在查询过程中的一些详细信息,MySQL查询优化器执行查询的过程中对查询计划的重要补充信息

你可能感兴趣的:(mysql)