全部产品
云市场

SQL 调优基础概念

更新时间:2019-11-20 17:19:50

在使用 DRDS 的过程中,因为种种原因,可能出现性能不符合预期的慢SQL。SQL 调优的过程,就是通过分析SQL的执行计划、各阶段运行时长等信息,找出拖慢SQL执行的原因,继而解决问题。

调优 SQL 的过程中,首先要理解何为 DRDS 的执行计划,这是一切调优的基础:执行计划告诉我们一条 SQL 是怎样执行的

DRDS 架构

DRDS 既可以看作一个中间件,也可以看作一个“计算存储分离”架构的数据库产品。当用户的一条查询 SQL(称为逻辑 SQL)发往 DRDS 节点时,我们会将其分成可下推的、和不可下推的两部分,如下图所示。可下推的部分也被称为物理 SQL

x

原则上,DRDS 会:

  • 尽可能将用户 SQL 下推到 MySQL 上执行
  • 对于无法下推的部分算子,选择最优的方式来执行

下推和执行计划

EXPLAIN 指令将会打印 SQL 的执行计划。它的用法非常简单:只要在 SQL 最前面加上 EXPLAIN 即可。下面我们通过几个例子来探索一下 DRDS 的执行方式。

例子一:

  1. > explain select c_custkey, c_name, c_address from customer where c_custkey = 42;
  2. LogicalView(tables="customer_2", sql="SELECT `c_custkey`, `c_name`, `c_address` FROM `customer` AS `customer` WHERE (`c_custkey` = ?)")

对于点查(主键查询)来说,DRDS 只要将 SQL 直接下发到主键对应的分片上即可。因此,执行计划中只有一个 LogicalView 算子,下发的物理 SQL 基本和逻辑 SQL 是一样的。

LogicalView 算子代表下推到 MySQL 执行的查询,更多信息参见“查询计划和基本算子”章节。

例子二:

  1. > explain select c_nationkey, count(*) from customer group by c_nationkey;
  2. HashAgg(group="c_nationkey", count(*)="SUM(count(*))")
  3. Gather(concurrent=true)
  4. LogicalView(tables="customer_[0-7]", shardCount=8, sql="SELECT `c_nationkey`, COUNT(*) AS `count(*)` FROM `customer` AS `customer` GROUP BY `c_nationkey`")

上述查询会统计:各个国家的客户数量分别有多少?考虑到分库分表,我们可以将它分成两个阶段来进行:

  1. 首先,在各个分表上进行 COUNT(*) 统计(这一步可被下推到 MySQL 上执行)
  2. 将结果汇总,将 COUNT(*) 的结果求 SUM(),得到最终的结果 (这一步需要 DRDS 节点来完成)

从执行计划上,也可以看出这一点。其中:

  • LogicalView 表示下发到各个分片的 SQL:按 nation 分组进行 count(*) 统计
  • Gather 算子表示收集各个分片的结果
  • HashAgg 是聚合(Aggregate)的一种实现:以 c_nationkey 作为分组键、求 count 的 SUM

更多的例子,请参见“执行计划和基本算子”这一章节。