前言
今天你并行了吗?在PolarDB 8.0中,我们领先MySQL官方版本,率先支持了SQL的并行执行,充分利用硬件多核多CPU的优势,大幅提高了类OLAP的查询性能,体现了自研PolarDB数据库极高的性价比。
如何深入分析SQL的并行执行情况,以协助DBA解决可能存在的性能瓶颈,是一个迫在眉睫的问题,因此PolarDB 8.0在Performance Schema中添加了对并行查询的支持,可以帮助DBA洞察并行执行过程中的各种情况,为后续的查询优化提供丰富的情报。下面我们就详细了解一下并行查询的分析过程。
准备工作
打开并行查询
若是等于0,意味着关闭并行模式。
当max_parallel_degree大于0时,表示允许最多有多少个worker参与并行执行, 建议设置为实例cpu 核数的一半。比如对于8core32g 的实例, 建议设置为4, 对于16core128g的实例,建议设置为8, 对于2核或4核的实例, 建议关掉并行查询功能。
打开performance_schema
注意: 打开performance_schema 需要重启实例, 因此用户请在合适时间进行设置
开启并行查询相关的消费者consumer
后续操作都是由实例的超级用户,或者库performance_schema 已经授权给当前用户
update performance_schema.setup_consumers
set ENABLED= 'YES'
where name like 'events_parallel_query_current' ;
update performance_schema.setup_consumers
set ENABLED= 'YES'
where name like 'events_parallel_operator_current' ;
update performance_schema.setup_consumers
set ENABLED= 'YES'
where name like 'events_parallel_query_history' ;
update performance_schema.setup_consumers
set ENABLED= 'YES'
where name like 'events_parallel_operator_history' ;
启动时自动开启对并行查询相关事件的监测。
在my.cnf中添加以下行:
performance-schema-instrument='parallel_query%=ON'
性能分析
(1)检测是否并行
当出现性能问题时,首先我们要确定查询是否真的是并行执行。虽然通过查看执行计划,我们可以看到执行计划是并行的执行计划,但这并不意味着在执行时一定会并行执行,不能并行执行的原因通常是资源不足,CPU、内存、线程等资源的限制都要求我们不能无限制的并行。如果并行不受限制的执行,可能会导致一个并行查询就耗光了所有的资源,从而导致其它所有任务都被堵塞,可用性也受到极大影响。
因此针对这个问题,系统提供了一个参数max_parallel_workers来限制同时执行的并行数量。max_parallel_workers指在同一时刻用于并行执行的worker线程的最大数目(系统硬性设置为实例cpu数的4倍)。当超过max_parallel_workers时,之后就不会再产生并行执行计划,即使这些查询的执行计划中并行执行计划最优。
我们不能实时的去查询每个执行计划,因此当查询执行完成后,需要一些方法去确定刚刚执行完成的查询是否以并行方式执行。在performance schema中的events_statements_current/events_statements_history可以查看某条查询是否以并行方式执行。
如果发现当前情况下, 原本预期应该是并行的查询,但变成非并行查询, 需要进一步分析
运行的SQL 是否可以并行, 查询并行查询文档,检查 “并行查询的限制” 一节, 比如当前表记录数小于20000行,无法满足并行查询
检查当前系统负荷是否比较重, 如果当前系统负荷,比如内存利用率已经接近实例上限或cpu负荷较重时,会退化为非并行查询。
查询当前连接的内部thread_id:
select thread_id from performance_schema.threads where processlist_id=connection_id();
然后执行以下SQL:
select th.thread_id,
processlist_id,
SQL_TEXT,
PARALLEL
from performance_schema.events_statements_history stmth,
performance_schema.threads th
where stmth.thread_id= th.thread_id
order by PARALLEL desc;
下图是在控制台dms上的输出结果
找到你关注的SQL 的thread_id, PARALLEL 状态。
注意:
查询出来的thread_id 很重要, 后续会大量依赖这个thread_id
直接从events_statements_xxx查到的thread_id与通过show processlist查到ID是两个完全不同的ID&#