使用Explain分析SQL执行计划

本文介绍了如何判断您当前使用的SQL语句能否使用列存索引加速功能。

判断方法

说明
  • 本文的TPC-H的实现基于TPC-H的基准测试,并不能与已发布的TPC-H基准测试结果相比较,本文中的测试并不符合TPC-H基准测试的所有要求。

  • 如何判断您需要查询的列是否被列存索引覆盖,请参考检查SQL语句中的表是否已创建列索引

  • 列存索引只能访问被列存索引覆盖到的数据列的数据,因此,当您需要查询的列都被列存索引覆盖时,便可以使用列存索引加速功能。

  • PolarDB MySQL版中,列存执行计划以横向树的格式输出,与行存执行计划的输出格式有一定的区分度,您可以通过查看执行计划的方式来判断某条SQL语句是否可以使用列存索引加速功能。示例如下:

    执行如下命令,查看SQL语句的执行计划:

    explain SELECT l_orderkey,sum(l_extendedprice * (1 - l_discount)) AS revenue,o_orderdate,o_shippriority
    FROM customer,orders,lineitem
    WHERE c_mktsegment = 'BUILDING'
    AND c_custkey = o_custkey
    AND l_orderkey = o_orderkey
    AND o_orderdate < date '1995-03-24'
    AND l_shipdate > date '1995-03-24'
    GROUP BY l_orderkey,o_orderdate,o_shippriority
    ORDER BY revenue DESC,o_orderdate\G;
    • 行存执行计划显示结果如下:

      +----+-------------+----------+------------+--------+---------------+---------+---------+--------------------------+---------+----------+----------------------------------------------+
      | id | select_type | table    | partitions | type   | possible_keys | key     | key_len | ref                      | rows    | filtered | Extra                                        |
      +----+-------------+----------+------------+--------+---------------+---------+---------+--------------------------+---------+----------+----------------------------------------------+
      |  1 | SIMPLE      | orders   | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL                     | 1482516 |    33.33 | Using where; Using temporary; Using filesort |
      |  1 | SIMPLE      | customer | NULL       | eq_ref | PRIMARY       | PRIMARY | 8       | tpch1g.orders.O_CUSTKEY  |       1 |    10.00 | Using where                                  |
      |  1 | SIMPLE      | lineitem | NULL       | ref    | PRIMARY       | PRIMARY | 8       | tpch1g.orders.O_ORDERKEY |       3 |    33.33 | Using where                                  |
      +----+-------------+----------+------------+--------+---------------+---------+---------+--------------------------+---------+----------+----------------------------------------------+
      3 rows in set, 1 warning (0.01 sec)
    • 列存执行计划显示结果如下:

      *************************** 1. row ***************************
      IMCI Execution Plan (max_dop = 8, max_query_mem = 3435134976):
      Project | Exprs: temp_table3.lineitem.L_ORDERKEY, temp_table3.SUM(lineitem.L_EXTENDEDPRICE * 1.00 - lineitem.L_DISCOUNT), temp_table3.orders.O_ORDERDATE, temp_table3.orders.O_SHIPPRIORITY
        Sort | Exprs: temp_table3.SUM(lineitem.L_EXTENDEDPRICE * 1.00 - lineitem.L_DISCOUNT) DESC,temp_table3.orders.O_ORDERDATE ASC
          HashGroupby | OutputTable(3): temp_table3 | Grouping: lineitem.L_ORDERKEY orders.O_ORDERDATE orders.O_SHIPPRIORITY | Output Grouping: lineitem.L_ORDERKEY, orders.O_ORDERDATE, orders.O_SHIPPRIORITY | Aggrs: SUM(lineitem.L_EXTENDEDPRICE * 1.00 - lineitem.L_DISCOUNT)
            HashJoin | HashMode: DYNAMIC | JoinMode: INNER | JoinPred: orders.O_ORDERKEY = lineitem.L_ORDERKEY
              HashJoin | HashMode: DYNAMIC | JoinMode: INNER | JoinPred: orders.O_CUSTKEY = customer.C_CUSTKEY
                CTableScan | InputTable(0): orders | Pred: (orders.O_ORDERDATE < 03/24/1995 00:00:00.000000)
                CTableScan | InputTable(1): customer | Pred: (customer.C_MKTSEGMENT = "BUILDING")
              CTableScan | InputTable(2): lineitem | Pred: (lineitem.L_SHIPDATE > 03/24/1995 00:00:00.000000)
      1 row in set (0.04 sec)

FAQ

当某条SQL语句的执行计划不是列存执行计划时,可能的原因有哪些?

  • SQL语句查询的数据列是否被列存索引覆盖,若数据列没有被列存索引覆盖,请为需要使用列存执行计划的数据列创建列存索引,创建列存索引请参见建表时创建列存索引的DDL语法动态增加或删除列存索引的DDL语法

  • 对于已开启行存/列存自动引流的集群地址,请确认参数设置中的loose_imci_ap_threshold参数值是否满足条件,即检查SHOW STATUS LIKE 'Last_query_cost'的值是否大于SHOW VARIABLES LIKE 'imci_ap_threshold'的值。若不满足,请参考配置自动引流阈值中的内容适当修改loose_imci_ap_threshold参数值。

  • 对于只读列存节点, 请确认参数设置中的loose_cost_threshold_for_imci参数值是否满足条件,即检查SHOW STATUS LIKE 'Last_query_cost'的值是否大于SHOW VARIABLES LIKE 'cost_threshold_for_imci'的值。若不满足,请参考配置自动引流阈值中的内容适当修改loose_cost_threshold_for_imci参数值。

  • 对于主节点、普通列存节点或未开启行存/列存自动引流的集群地址,请切换至开启行存/列存自动引流的集群地址或者直接连接只读列存节点。