在使用PolarDB-X的过程中,可能出现性能不符合预期的慢SQL。SQL调优的过程,就是通过分析SQL的执行计划、各阶段运行时长等信息,找出导致SQL执行慢的原因,继而解决问题。
PolarDB-X架构
PolarDB-X是一个支持计算存储分离架构的数据库产品。当一条查询SQL(称为逻辑SQL)发往PolarDB-X节点时,PolarDB-X会将其分成可下推的、和不可下推的两部分,可下推的部分也被称为物理SQL。
原则上,PolarDB-X会:
- 尽可能将用户SQL下推到MySQL上执行。
- 对于无法下推的部分算子,选择最优的方式来执行。
下推和执行计划
EXPLAIN指令将会打印SQL的执行计划。它的用法非常简单:只要在SQL最前面加上EXPLAIN
即可。下面通过几个例子来展示PolarDB-X的执行方式。
示例一:
> explain select c_custkey, c_name, c_address from customer where c_custkey = 42; LogicalView(tables="customer_2", sql="SELECT `c_custkey`, `c_name`, `c_address` FROM `customer` AS `customer` WHERE (`c_custkey` = ?)")
对于带有主键条件的查询来说,PolarDB-X只要将SQL直接下发到主键对应的分片上即可。因此,执行计划中只有一个LogicalView
算子,下发的物理SQL基本和逻辑SQL是一样的。
LogicalView
算子代表下推到MySQL执行的查询,请参见执行计划和基本算子。
示例二:
> explain select c_nationkey, count(*) from customer group by c_nationkey; HashAgg(group="c_nationkey", count(*)="SUM(count(*))") Gather(concurrent=true) LogicalView(tables="customer_[0-7]", shardCount=8, sql="SELECT `c_nationkey`, COUNT(*) AS `count(*)` FROM `customer` AS `customer` GROUP BY `c_nationkey`")
上述查询会统计:各个国家的客户数量分别有多少?考虑到分库分表,可以将它分成两个阶段来进行:
- 在各个分表上进行
COUNT(*)
统计(这一步可被下推到MySQL上执行)。 - 将结果汇总,将
COUNT(*)
的结果执行SUM()
,得到最终的结果(这一步需要PolarDB-X节点来完成)。
从执行计划上,也可以看出这一点。其中:
LogicalView
表示下发到各个分片的SQL按nation分组进行COUNT(*)
统计。Gather
算子表示收集各个分片的结果。HashAgg
是聚合(Aggregate)的一种实现方式,以c_nationkey
作为分组键将COUNT(*)
的结果求SUM()
。
更多的例子,详情请参见执行计划和基本算子。