范围联接

Vertica 为联接 ON 子句中的 <、<=、>、>= 和 BETWEEN 谓词进行了性能优化。如果一个表的列限定在另一个表的两个列所指定的范围内,这些优化将特别有用。

键范围

多个连续的键值可映射到相同的维度值。例如,以 IPv4 地址表及其所有者为例。因为大型 IP 地址子网(范围)可属于同一个所有者,所以此维度可表示为:

=> CREATE TABLE ip_owners(
      ip_start INTEGER,
      ip_end INTEGER,
      owner_id INTEGER);
=> CREATE TABLE clicks(
      ip_owners INTEGER,
      dest_ip INTEGER);

将点击流与其目标相关联的查询可以使用与以下使用范围优化的联接类似的联接:

=> SELECT owner_id, COUNT(*) FROM clicks JOIN ip_owners
   ON clicks.dest_ip BETWEEN ip_start AND ip_end
   GROUP BY owner_id;

要求

<、<=、>、>= 或 BETWEEN 运算符必须作为最高级别的连接谓词显示,才能使范围联接优化起作用,如以下示例所示:

`BETWEEN `作为唯一的谓词:

```
=> SELECT COUNT(*) FROM fact JOIN dim
    ON fact.point BETWEEN dim.start AND dim.end;

```

比较运算符作为最高级别的谓词(在 `AND` 内):

```
=> SELECT COUNT(*) FROM fact JOIN dim
    ON fact.point > dim.start AND fact.point < dim.end;

```

`BETWEEN `作为最高级别的谓词(在 `AND` 内):

```
=> SELECT COUNT(*) FROM fact JOIN dim
   ON (fact.point BETWEEN dim.start AND dim.end) AND fact.c <> dim.c;

```

查询未优化,因为 `OR` 是最高级别的谓词(反意连接词):

```
=> SELECT COUNT(*) FROM fact JOIN dim
   ON (fact.point BETWEEN dim.start AND dim.end) OR dim.end IS NULL;

```

注意

  • 在许多用例中,范围联接查询中的表达式都得到了优化。

  • 如果范围列可以包含 NULL 值(指示它们是开放式的),则将 NULL 替换为非常大或非常小的值,即可使用范围联接优化:

    => SELECT COUNT(*) FROM fact JOIN dim
       ON fact.point BETWEEN NVL(dim.start, -1) AND NVL(dim.end, 1000000000000);
    
  • 如果同一个 ON 子句中有一个以上范围谓词集,谓词的指定顺序可能会影响优化的效果:

    => SELECT COUNT(*) FROM fact JOIN dim ON fact.point1 BETWEEN dim.start1 AND dim.end1
       AND fact.point2 BETWEEN dim.start2 AND dim.end2;
    

    优化器会选择第一个范围进行优化,因此编写查询,确保让您最想优化的范围最先出现在语句中。

  • 物理架构的任何特性都不会直接影响范围联接优化的使用;不需要对架构进行调试即可受益于优化。

  • 范围联接优化可应用于不包含任何其他谓词的联接,也可应用于 HASH MERGE 联接。

  • 要确定优化是否正在使用,请在 EXPLAIN 计划中搜索 RANGE