GPORCA特性和增强

    GPORCA还包括下面这些优化增强:

    • 改进的连接排序
    • 连接-聚集重排序
    • 排序顺序优化
    • 查询优化中包括的数据倾斜估计

    上级主题: 关于GPORCA

    GPORCA包括这些对分区表上查询的增强:

    • 改进了分区消除。
    • 支持统一多级分区表。有关统一多级分区表的信息请见
    • 查询计划可以包含分区选择器操作符。
    • 不在EXPLAIN计划中枚举分区。

      对于涉及静态分区选择的查询,在其中会将分区键与常量进行比较,GPORCA会在EXPLAIN输出的分区选择器操作符下面列出要被扫描的分区数。这个示例分区选择器操作符展示了过滤条件和选中的分区数:

      对于涉及动态分区选择的查询,在其中会将分区键与变量进行比较,要扫描的分区数只有在查询执行时才能知道。选中的分区不会显示在EXPLAIN输出中。

    • 计划尺寸与分区数无关。

    • 由于分区数导致的内存不足错误被减少。

    这个CREATE TABLE命令的例子创建一个范围分区表。

    1. date date, yr_qtr int)
    2. range partitioned by yr_qtr;

    GPORCA改进了针对分区表的这些类型的查询:

    • 全表扫描。计划中不会枚举分区。

      1. SELECT * FROM sales;
      1. SELECT * FROM sales WHERE yr_qtr = 201501;
    • 范围选择。会执行分区消除。

      1. SELECT * FROM sales WHERE yr_qtr BETWEEN 201601 AND 201704 ;
    • 涉及到分区表的连接。在下面这个例子中,分区过的维度表date_dim被连接到事实表catalog_sales

      1. SELECT * FROM catalog_sales
      2. WHERE date_id IN (SELECT id FROM date_dim WHERE month=12);

    GPORCA更有效地处理子查询。子查询是嵌套在外层查询块里面的查询。在下面的查询中,WHERE子句中的SELECT是一个子查询。

    GPORCA还能更有效地处理含有相关子查询(CSQ)的查询。相关子查询是使用来自外层查询的值的子查询。在下面的查询中,price列被使用在外层查询和子查询中。

    1. SELECT * FROM part p1
    2. WHERE price > (SELECT avg(price) FROM part p2

    GPORCA为下列类型的子查询生成更有效的计划:

    • SELECT列表中的CSQ。

      1. SELECT *,
      2. (SELECT min(price) FROM part p2 WHERE p1.brand = p2.brand)
      3. AS foo
      4. FROM part p1;
    • 析取(OR)过滤条件中的CSQ。

      1. SELECT FROM part p1 WHERE p_size > 40 OR
      2. p_retailprice >
      3. (SELECT avg(p_retailprice)
      4. FROM part p2
      5. WHERE p2.p_brand = p1.p_brand)
    • 具有越级关联的嵌套CSQ

      1. IN (SELECT p_partkey FROM part p2 WHERE p2.p_retailprice =
      2. (SELECT min(p_retailprice)
      3. FROM part p3
      4. WHERE p3.p_brand = p1.p_brand)
      5. );

      注意: 传统查询优化器不支持具有越级关联的嵌套CSQ。

    • 有聚集和不等于的CSQ。下面这个例子包含一个有不等于的CSQ。

      1. SELECT * FROM part p1 WHERE p1.p_retailprice =
      2. (SELECT min(p_retailprice) FROM part p2 WHERE p2.p_brand <> p1.p_brand);

    GPORCA处理含有WITH子句的查询。WITH子句也被称为公共表表达式(CTE),它会生成只在该查询中存在的临时表。下面这个查询例子包含一个CTE。

    1. WITH v AS (SELECT a, sum(b) as s FROM T where c < 10 GROUP BY a)
    2. SELECT *FROM v AS v1 , v AS v2
    3. WHERE v1.a <> v2.a AND v1.s < v2.s;

    作为查询优化的一部分,GPORCA可以把谓词下推到一个CTE中。对于下面的例子查询,GPORCA把等于谓词推到了CTE。

    1. WITH v AS (SELECT a, sum(b) as s FROM T GROUP BY a)
    2. SELECT *
    3. FROM v as v1, v as v2, v as v3
    4. WHERE v1.a < v2.a
    5. AND v1.s < v3.s
    6. AND v1.a = 10
    7. AND v2.a = 20

    GPORCA可以处理这些类型的CTE:

    • 定义一个或者多个表的CTE。在下面的这个查询中,CTE定义两个表。

      1. WITH cte1 AS (SELECT a, sum(b) as s FROM T
      2. cte2 AS (SELECT a, s FROM cte1 where s > 1000)
      3. SELECT *
      4. FROM cte1 as v1, cte2 as v2, cte2 as v3
      5. WHERE v1.a < v2.a AND v1.s < v3.s;
    • 嵌套CTE。

      1. WITH v AS (WITH w AS (SELECT a, b FROM foo
      2. WHERE b < 5)
      3. SELECT w1.a, w2.b
      4. FROM w AS w1, w AS w2
      5. WHERE w1.a = w2.a AND w1.a > 2)
      6. SELECT v1.a, v2.a, v2.b
      7. FROM v as v1, v as v2
      8. WHERE v1.a < v2.a;

    GPORCA含有对DML操作(例如INSERT、UPDATE和DELETE)的增强。

    • 查询计划中的DML节点是一个查询计划操作符。
      • 可以作为一个常规节点(目前只有顶层切片)出现在计划中的任何地方
      • 可以有消费者
    • UPDATE操作使用查询计划操作符Split并且支持这些操作:

      • 表的分布键列上的UPDATE操作。
      • 表的分区键列上的UPDATE操作。

      这个计划的例子展示了Split操作符。

      1. QUERY PLAN
      2. --------------------------------------------------------------
      3. Update (cost=0.00..5.46 rows=1 width=1)
      4. -> Redistribute Motion 2:2 (slice1; segments: 2)
      5. Hash Key: a
      6. -> Result (cost=0.00..3.23 rows=1 width=48)
      7. -> Split (cost=0.00..2.13 rows=1 width=40)
      8. -> Table Scan on dmltest
    • 新的查询计划操作符Assert被用于约束检查。

      这个计划的例子展示了Assert操作符。