专栏首页ClickHouse的秘密基地尝鲜ClickHouse原生EXPLAIN查询功能

尝鲜ClickHouse原生EXPLAIN查询功能

在之前的一篇文章中,我曾经介绍过如何借助 ClickHouse 的服务日志查看 SQL 执行计划,从而变相达到 EXPLAIN 查询的目的。

在先前的方法中,由于 CH 没有原生的 EXPLAIN 查询,所以如果想要看到执行计划,那么 SQL 语句必须被真正的执行,所以这种方法只能作为一种事后分析,有着明显的缺点。

现在,事情有了转机。在本周的早些时候,一个名为 Initial explain #11873 的 PR 被合入了主线。是的,新鲜出炉的,ClickHouse 原生的 EXPLAIN 查询诞生了。

那还不赶快尝鲜一下 ?!

由于这个 PR 本周才被合并,所以目前在官方提供的编译好的安装包中是看不到这个功能的,只能通过 master 分支自行编译。

如上图所示,是我在本地编译的版本,版本号是 20.6。所以可以肯定的是在这个版本中可以使用到 CH 原生的 EXPLAIN 查询。希望后续可以 backport 到低版本。

EXPLAIN 的完整语法如下所示:

EXPLAIN [ PLAN | AST | SYNTAX | PIPELINE ] [setting = value, ...] SELECT ...

其中:

PLAN 用于查看执行计划;

AST 用于查看语法树;

SYNTAX 用于优化语法;

PIPELINE 用于查看 PIPELINE 计划。

PLANPIPELINE 还可以进行额外的显示设置,这一部分放到后续的演示过程中解释。

接下来就让我们来挨个尝鲜吧。

  • PLAN

PLAN是最常用的功能,即查看 SQL 执行计划,例如执行:

EXPLAIN PLAN SELECT 1:
Union
  Expression (Projection)
    Expression (Before ORDER BY and SELECT)
      ReadFromStorage (Read from SystemOne)

4 rows in set. Elapsed: 0.001 sec. 

如上所示,该 SQL 的执行计划被显示出来了。

PLAN 是 EXPLAIN 的默认值,所以 PLAN 修饰词可以省略,现在我们换条复杂一点的 SQL,执行:

EXPLAIN
SELECT 
    database,
    table,
    column,
    any(type),
    sum(column_data_compressed_bytes) AS compressed,
    sum(column_data_uncompressed_bytes) AS uncompressed,
    round(uncompressed / compressed, 2) AS ratio,
    compressed / sum(rows) AS bpr,
    sum(rows)
FROM system.parts_columns
WHERE active AND (database != 'system')
GROUP BY 
    database,
    table,
    column
ORDER BY 
    database ASC,
    table ASC,
    column ASC
FORMAT TSV

查看结果:

Union
  Expression (Projection)
    MergingSorted (Merge sorted streams for ORDER BY)
      MergeSorting (Merge sorted blocks for ORDER BY)
        PartialSorting (Sort each block for ORDER BY)
          Expression (Before ORDER BY and SELECT)
            Aggregating
              Expression (Before GROUP BY)
                Filter (WHERE)
                  ReadFromStorage (Read from SystemPartsColumns)

10 rows in set. Elapsed: 0.003 sec. 

该 SQL 的每一步执行计划都被显示出来了,此时我们进一步观察 CH 的日志:

{bbfc1521-13fe-4d5a-b99f-4d8f6ed9dd6c} <Debug> executeQuery: (from 127.0.0.1:59522) EXPLAIN SELECT database, table, column, any(type), sum(column_data_compressed_bytes) AS compressed, sum(column_data_uncompressed_bytes) AS uncompressed, round(uncompressed / compressed, 2) AS ratio, compressed / sum(rows) AS bpr, sum(rows) FROM system.parts_columns WHERE active AND database != 'system' GROUP BY database, table, column ORDER BY database ASC, table ASC, column ASC;
2020.07.12 02:07:46.580977 [ 8451277 ] {bbfc1521-13fe-4d5a-b99f-4d8f6ed9dd6c} <Trace> InterpreterSelectQuery: FetchColumns -> Complete
2020.07.12 02:07:46.581329 [ 8451277 ] {bbfc1521-13fe-4d5a-b99f-4d8f6ed9dd6c} <Debug> executeQuery: Query pipeline:
One

2020.07.12 02:07:46.581556 [ 8451277 ] {bbfc1521-13fe-4d5a-b99f-4d8f6ed9dd6c} <Information> executeQuery: Read 10 rows,

可以看到,真正执行 EXPLAIN 查询的计划是:

Query pipeline:
One

我们输入的 SQL 并没有被真正执行,所以这种方式可以用于事前分析。

EXPLAIN PLAN 目前还可以设置 3 个参数,它们分别是:

header,打印计划中各个步骤的 head 说明,默认关闭;

description,打印计划中各个步骤的描述,默认开启;

actions,打印计划中各个步骤的详细信息,默认关闭。

例如执行:

EXPLAIN header=1, actions=1 SELECT 1;

将会看到:

Union
Header: 1 UInt8 Const(size = 0, UInt8(size = 1))
  Expression (Projection)
  Header: 1 UInt8 Const(size = 0, UInt8(size = 1))
  Actions: PROJECT 1
    Expression (Before ORDER BY and SELECT)
    Header: _dummy UInt8 UInt8(size = 0)
            1 UInt8 Const(size = 0, UInt8(size = 1))
    Actions: COPY _dummy = dummy (can replace)
             REMOVE dummy
             ADD 1 UInt8 Const(UInt8)
      ReadFromStorage (Read from SystemOne)
      Header: dummy UInt8 UInt8(size = 0)

13 rows in set. Elapsed: 0.001 sec.
  • AST

AST 可以查看 SQL 的语法树,例如执行:

EXPLAiN AST SELECT * FROM `system`.numbers n LIMIT 10000

返回语法树结构:

SelectWithUnionQuery (children 1)
 ExpressionList (children 1)
  SelectQuery (children 3)
   ExpressionList (children 1)
    Asterisk
   TablesInSelectQuery (children 1)
    TablesInSelectQueryElement (children 1)
     TableExpression (children 1)
      Identifier system.numbers (alias n)
   Literal UInt64_10000

10 rows in set. Elapsed: 0.001 sec.
  • SYNTAX

SYNTAX 可以帮助我们优化 SQL 语句,例如下面的这条 SQL 语句:

SELECT number = 1 ? 'hello' : (number = 2 ? 'world' : 'xyz') FROM numbers(10);

通过 SYNTAX 优化:

SET optimize_if_chain_to_multiif = 1;
EXPLAIN SYNTAX SELECT number = 1 ? 'hello' : (number = 2 ? 'world' : 'xyz') FROM numbers(10);

返回优化后的语句:

SELECT multiIf(number = 1, \'hello\', number = 2, \'world\', \'xyz\')
FROM numbers(10)
  • PIPELINE

查看 PIPELINE 过程,例如执行:

EXPLAIN PIPELINE SELECT sum(number) FROM numbers_mt(100000) GROUP BY number % 20

会返回:

(Union)
Converting
  (Expression)
  ExpressionTransform
    (Expression)
    ExpressionTransform
      (Aggregating)
      Resize 8 → 1
        AggregatingTransform × 8
          (Expression)
          ExpressionTransform × 8
            (ReadFromStorage)
            NumbersMt × 8 0 → 1

13 rows in set. Elapsed: 0.002 sec. 

PIPELINE 目前也可以设置 3 个参数,它们分别是:

header,打印计划中各个步骤的 head 说明,默认关闭;

graph,用DOT图形语言描述管道图,默认关闭;

actions,如果开启了graph,紧凑打印打,默认开启。

例如执行:

EXPLAIN PIPELINE header=1,graph=1 SELECT sum(number) FROM numbers_mt(100000) GROUP BY number % 20

会看到:

digraph
{
  rankdir="LR";
  { node [shape = box]
    subgraph cluster_0 {
      label ="Aggregating";
      style=filled;
      color=lightgrey;
      node [style=filled,color=white];
      { rank = same;
        n3 [label="AggregatingTransform × 8"];
        n4 [label="Resize"];
      }
    }
    subgraph cluster_1 {
      label ="ReadFromStorage";
      style=filled;
      color=lightgrey;
      node [style=filled,color=white];
      { rank = same;
        n1 [label="NumbersMt × 8"];
      }
    }
    subgraph cluster_2 {
      label ="Union";
      style=filled;
      color=lightgrey;
      node [style=filled,color=white];
      { rank = same;
        n7 [label="Converting"];
      }
    }
    subgraph cluster_3 {
      label ="Expression";
      style=filled;
      color=lightgrey;
      node [style=filled,color=white];
      { rank = same;
        n5 [label="ExpressionTransform"];
      }
    }
    subgraph cluster_4 {
      label ="Expression";
      style=filled;
      color=lightgrey;
      node [style=filled,color=white];
      { rank = same;
        n2 [label="ExpressionTransform × 8"];
      }
    }
    subgraph cluster_5 {
      label ="Expression";
      style=filled;
      color=lightgrey;
      node [style=filled,color=white];
      { rank = same;
        n6 [label="ExpressionTransform"];
      }
    }
  }
  n3 -> n4 [label="× 8
modulo(number, 20) UInt8 UInt8(size = 0)
sum(number) UInt64 UInt64(size = 0)"];
  n4 -> n5 [label="
modulo(number, 20) UInt8 UInt8(size = 0)
sum(number) UInt64 UInt64(size = 0)"];
  n1 -> n2 [label="× 8
number UInt64 UInt64(size = 0)"];
  n5 -> n6 [label="
modulo(number, 20) UInt8 UInt8(size = 0)
sum(number) UInt64 UInt64(size = 0)"];
  n2 -> n3 [label="× 8
number UInt64 UInt64(size = 0)
modulo(number, 20) UInt8 UInt8(size = 0)"];
  n6 -> n7 [label="
sum(number) UInt64 UInt64(size = 0)"];
}

77 rows in set. Elapsed: 0.002 sec. 

借助这些信息,我们可以很方便的将其进行可视化。

在 ClickHouse 有了原生的 EXPLAIN 查询之后,日常工作中我们对于 SQL 的调优和问题排查工作就会更加便捷了。

本文分享自微信公众号 - ClickHouse的秘密基地(chcave),作者:凯朱

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何在ClickHouse中查看SQL执行计划

    ClickHouse目前并没有直接提供EXPLAIN查询,但是借助后台的服务日志,也能变相实现EXPLAIN的功能。

    Nauu
  • 2021年ClickHouse最王炸功能来袭,性能轻松提升40倍

    各位,今年 ClickHouse 最王炸的功能来啦,没错,就是期待已久的 Projection (投影) 功能。ClickHouse 现在的功能已经非常丰富强大...

    Nauu
  • ClickHouse王炸功能即将来袭?

    众所周知,MySQL 的用户群体很大,为了能够增强数据的实时性,很多解决方案会利用 binlog 将数据写入到 ClickHouse。

    Nauu
  • 一个比 MySQL 快 800 多倍的数据库...

    大家好呀!这里是爱学习的 Guide!今天给大家科普一个速度快到飞起的数据库——ClickHouse。

    Guide哥
  • 初探ClickHouse的RBAC权限功能

    在4.28号的线上 Meetup 中,朵夫介绍了 ClickHouse 的一项新特性,即基于角色的RBAC权限功能,当时我就觉得这将会是一项实用的功能。

    Nauu
  • 超快!大数据分析引擎ClickHouse

    ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。

    凹谷
  • ClickHouse源码笔记4:FilterBlockInputStream, 探寻where,having的实现

    Selection是关系代数之中重要的一个的一个运算,通常也会用σ符合来selection的实现。

    HappenLee
  • ClickHouse源码笔记4:FilterBlockInputStream, 探寻where,having的实现

    Selection是关系代数之中重要的一个的一个运算,通常也会用σ符合来selection的实现。

    HappenLee
  • ClickHouse为何如此之快?

    作为一个拥有ClickHouse信仰标签的忠实粉丝,我自然也是追寻谜底的一份子。在我苦苦寻觅许久之后,今天,终于被我找到了答案。所以特地拿来与各位分享,谜底就在...

    Nauu
  • ClickHouse和他的朋友们(15)Group By 为什么这么快

    在揭秘 ClickHouse Group By 之前,先聊聊数据库的性能对比测试问题。在虎哥看来,一个“讲武德”的性能对比测试应该提供什么信息呢?

    老叶茶馆
  • Clickhouse一个查询是如何完成的?

    Parser和Interpreter是非常重要的两组接口:Parser负责创建AST对象,Interpreter解释器则负责解释AST,并进一步创建查询的执行p...

    felixxdu
  • ClickHouse的核心特性及架构

    导读:随着业务的迅猛增长,Yandex.Metrica目前已经成为世界第三大Web流量分析平台,每天处理超过200亿个跟踪事件。能够拥有如此惊人的体量,在它背后...

    zhisheng
  • Clickhouse的实践之路

    在数据量日益增长的当下,传统数据库的查询性能已满足不了我们的业务需求。而Clickhouse在OLAP领域的快速崛起引起了我们的注意,于是我们引入Clickho...

    Spark学习技巧
  • [业界方案] ClickHouse业界解决方案学习笔记

    本文通过分析总结几篇文章来看目前工业界可能偏好的解决方案。学习目的是:大致知道其应用领域,技术特点和未来方向,看看目前工作中是否可以用到,或者当以后选型时候能够...

    罗西的思考
  • 真是秀,ClickHouse批量导入还可以这样玩?

    用过 HBase 的同学应该都知道,当批量导入数据的时候,可以利用 Spark 这样的计算引擎,直接将数据生成 HFile 一次性导入到 HBase,既有效地分...

    Nauu
  • 《这么多MergeTree 表引擎,我该怎么选?》- part 1

    第一性原理这个概念大家应该不会陌生,它原本是由古希腊哲学家亚里士多德提出的,意指“在系统中会存在一个最基本的命题,它不能被违背或者删除”。

    Nauu
  • 干货 | 携程ClickHouse日志分析实践

    Gavin Zhu,携程软件技术专家,负责监控系统运维开发、ES系统运维及Clickhouse技术应用推广及运维工作。

    携程技术
  • 使用ClickHouse对每秒6百万次请求进行HTTP分析

    我们在Cloudflare的一个大规模数据基础架构挑战是为我们的客户提供HTTP流量分析。我们所有客户都可以通过两种方式使用HTTP分析:

    后场技术
  • 看云上 ClickHouse 如何做计算存储分离

    12月6日-7日,由InfoQ 中国主办的综合性技术盛会QCon全球软件开发大会深圳站召开。QCon 内容源于实践并面向社区,演讲嘉宾依据热点话题,面向资深的...

    腾讯QQ大数据

扫码关注云+社区

领取腾讯云代金券