【高性能MySQL】第六章查询性能优化 查询优化器局限

刚才误关了浏览器,啊~~~

6.5MySQL查询优化器局限性

6.5.1关联子查询

where子查询实现的非常糟糕,最糟一类where包含in

优化

exists等效改写:

或使用group_concat()在in中构造由逗号分隔的列表:【

   GROUP_CONCAT()函数,主要用来处理一对多的查询结果,通常会结合GROUP BY一起使用

GROUP_CONCAT([DISTINCT] expr [,expr ...]

             [ORDER BY {unsigned_integer | col_name | expr}

                 [ASC | DESC] [,col_name ...]]

             [SEPARATOR str_val])

GROUP_CONCAT后,SELECT里如果使用了LIMIT是不起作用的

SELECT
    s.stu_id          AS  studentId,
    s.stu_name     AS  studentName,
//数值类型的数据转化成二进制BLOB类型
//CAST(expr AS type)或CONVERT(expr, type)将数值类型的数据转化成字符串
    GROUP_CONCAT(CAST(c.course_id AS CHAR) ORDER BY c.course_id) AS courseId,
    GROUP_CONCAT(c.course_name)  AS  studentCourse
FROM
    student s
LEFT JOIN
    stu_course sc
ON
    s.stu_id = sc.stu_id
LEFT JOIN
    course c
ON
    sc.course_id = c.course_id
GROUP BY
    studentId

如何用好关联子查询

上面说子查询不好,但是没有绝对真理,具体问题具体分析,explain好工具。值得利用:通过测试验证猜想

6.5.2union的限制

如希望union各个子句能据limit取部分结果集,或希望先排好序再合并结果集,要在union各个子句中分别使用这些个子句

6.5.3索引合并优化

where子句包多个复杂条件、mysql能访问单个表的多个索引以合并和交叉过滤的方式来定位需要查找的行

6.5.4等值传递:

某些时候,等值传递会带来些额外消耗

6.5.5并行执行

mysql无法利用多核特性来并行执行查询

6.5.6哈希关联

参考第5章自定义哈希索引

6.5.7松散索引扫描

mysql5.6之后的版本,通过索引条件下推方式解决松散索引扫描的一些限制

explain的extra字段显示using index for group-by 表示使用了松散索引扫描

6.6查询优化器的提示hint

在查询中加入相应的提示,可控制该查询的执行计划

HIGHT_PRIORITY 和 LOW_PRIORITY  执行顺序相关

       当多个语句同时访问某一个表时,哪些语句的优先级高、低

        H*:select语句,mysql将其放在表队列的前面;insert语句,简单抵消全局low_priority设置的影响

        L*:让语句一直等待

        对使用表锁的引擎有效,不要在innodb或有细粒度锁机制 并发控制的引擎中使用:导致并发插入被禁

DELAYED:对insert replace有效

       将 使用该提示的语句 立即返回给客户端,将插入的行数据放入到缓存区 在表空闲时批量将数据写入

       不是all的存储引擎都支持,会导致last_insert_id无法正常工作

STRAIGHT_JOIN: 关联顺序相关

        放在select后:查询中all表按在语句中顺序进行关联

        可放任何两个关联表的名字间:固定器前后两表的关联顺序

        可使explain语句查优化器选择的关联顺序,然后使用该提示重写查询,在看顺序,升级需重审视查询

SQL_SMALL_RESULT和SQL_BIG_RESULT:select

        告诉优化器对group by或distinct查询如何使用临时表及排序

       *SM*:告诉器结果集会很小,可将结果集放在内存的索引临时表,避免排序

       *B*:告诉器结果集可能非常大,建议使用磁盘临时表做排序操作

SQL_BUFFER_RESULT:

       告诉器将查询结果放入到一临时表,尽可能快地释放表锁,服务器端需more内存,客户端稍解放

SQL_CACHE和SQL_NO_CACHE:

        这个结果集是否应该缓存在查询缓存中

SQL_CALC_FOUND_ROWS:

        让返回的结果集包含more信息,不应该使用,可通found_row获得这个值

FOR UPDATE和LOCK IN SHARE MODE:只对实现了行级锁的引擎有效

         控制select语句锁机制,会对符合查询条件的数据行加锁,避免使用,锁挣用

USE INDEX 、IGNORE INDEX和FORCE INDEX:

         使用或不使用哪些索引来查询记录

         5.1及后可通过FOR ORDER BY 和FOR GROUP BY指定是否对排序和分组有效

         force index同use index(除for*会告诉优化器全表扫描成本高于索引扫描)

5.6新增:

1、optimizer_search_depth:控制优化器在穷举执行计划时的限度

2、optimizer_prune_level:默认打开,让优化器据需要扫描的行数来决定是否跳过某些执行计划

3、optimizer_switch:包含些开启/关闭优化器特性的标志位

前两个参数控制优化器走一些捷径:让优化器处理复杂sql时仍高效,但也可能错过些真正最优的执行计划

自定义设置的  优化器提示  可能使新版的优化策略失效:耍小聪明 不太好 

6.7优化特定类型的查询

多数优化技巧和特定版本有关,注意版本

6.7.1优化count查询

作用:

1、统计某个列的数量、行数,如果count()指定列或列的表达式,统计的是这个表达式有值的结果数 非null

2、统计结果集的行数,mysql确认()内表达式值不为空,便是在统计行数

关于MyISAM:无where的count会非常快

取小的范围、近似值、汇总表、缓存系统

6.7.2优化关联查询

1、确保on或using子句中列上有索引,无其他理由,只在关联顺序的第二张表相应列建索引

2、group by 和order by 的表达式只涉及一个表中的列,才能使用索引

3、版本升级,注意关联语法、运算符优先级等可能发生变化的地方

6.7.3优化子查询

尽可能使用关联查询代替,mysql5.6及更新的版本或mariadb可忽略

6.7.4优化group by和distinct

可使用索引来优化

无法使用索引时:

    group by使用临时表或文件排序做分组,可通过提示sql_big_result和sql_samll_result‘指挥’优化器

    对关联查询做分组,且按照查找表的某个列进行分组,采用查找表的标识列来分组的效率会更高

优化group by with rollup:

    如对返回分组结果再做一次超级聚合,可使用with rollup实现,尽可能将with rollup功能转移到程序中处理

6.7.5优化limit分页

偏移量很大但是要的数据很少,优化 要么在页面中限制分页的数量 要么优化大偏移量的性能

1、尽可能使用索引覆盖扫描,据需要做一次关联操作再返回需要的列

2、

延迟关联:提效率,扫描尽可能少的页,获取要访问的记录后据关联列回原表查询需的列

3、将limit查询转换为已知位置的查询,让mysql通过范围扫描获得对应的结果

        预先计算出边界值,between * and *,limit 20 ,下次从20个后开始

6.7.6优化SQL_CALC_FOUND_ROWS:

     分页时,技巧在limit语句中加SQL_CALC_FOUND_ROWS提示,可获得去掉limit后满足条件的行数,作为分页的总数,会扫描all满足条件的行、抛弃不需要的行,代价可能有点高

     1、将具体的页数换成“下一页”按钮,每页显示20条但查询21条哦,21条存在则有数据,否则没有数据(哈哈~优秀优秀)

     2、先获取缓存较多数据,每次分页从缓存中获取:程序据结果集大小采取不同策略,<1000 显示all分页链接 >1000 灵活设计     比 找到all再抛弃效率高

     使用explain结果中的rows值作为结果集总数的近似值,需精确结果再count(*)

6.7.7用户union查询

通过创建、填充临时表来执行union查询,很多优化策略在union中无法很好使用,需要手工将where 、limit、 order by 等下推到union各个子查询中,让优化器充分利用这些条件进行优化

除非需要服务器消除重复行,否则一定要使用union all ,无all ,mysql会给临时表加上distinct:导致对临时表做唯一性查询,代价高

6.7.8静态查询分析

percona toolkit 的pt-query-advisor能解析查询日志、分析查询模式、给出all可能会有潜在问题的查询、给出建议

 

猜你喜欢

转载自blog.csdn.net/ma15732625261/article/details/81608667