使用子查询进行DB2连接优化(NLJOIN与HSJOIN)

时间:2015-03-09 10:30:54

标签: sql join db2 query-optimization db2-luw

我试图修复用于计算数据的查询的性能。在其中一个查询中,DB2 LUW的优化器选择执行嵌套循环连接而不是散列连接。

有问题的查询(导致NLJOIN)

with
  source1 as (select COALESCE(CAST("LOGICAL_KEY" AS CHARACTER VARYING(4000)), ']#[') as LOGICAL_KEY from "SAMPLE"."SOURCE1"),
  source2 as (select COALESCE(CAST("LOGICAL_KEY" AS CHARACTER VARYING(4000)), ']#[') as LOGICAL_KEY from "SAMPLE"."SOURCE2")
select count(*) from (
  SELECT
    "a"."LOGICAL_KEY",
    "b"."LOGICAL_KEY"
  FROM
   source1 "a",
   source2 "b"
 WHERE
   "a"."LOGICAL_KEY" =
   "b"."LOGICAL_KEY"
);

但是,当我首先创建子查询表时,优化器会执行散列连接。

优化查询(导致HSJOIN)

CREATE TABLE "SAMPLE"."TMP_SOURCE1" ("LOGICAL_KEY" VARCHAR(4000 BYTE));
CREATE TABLE "SAMPLE"."TMP_SOURCE2" ("LOGICAL_KEY" VARCHAR(4000 BYTE));

insert into "SAMPLE"."TMP_SOURCE1" select COALESCE(CAST("LOGICAL_KEY" AS CHARACTER VARYING(4000)), ']#[') LOGICAL_KEY from "SAMPLE"."SOURCE1";
insert into "SAMPLE"."TMP_SOURCE2" select COALESCE(CAST("LOGICAL_KEY" AS CHARACTER VARYING(4000)), ']#[') LOGICAL_KEY from "SAMPLE"."SOURCE2";

select count(*) from (
  SELECT
    "a"."LOGICAL_KEY",
    "b"."LOGICAL_KEY"
  FROM
    (select * from "SAMPLE"."TMP_SOURCE1") "a",
    (select * from "SAMPLE"."TMP_SOURCE2") "b"
  WHERE
    "a"."LOGICAL_KEY" =
    "b"."LOGICAL_KEY"
);

为什么DB2为相同的数据选择不同的路径?有没有办法强制结构与子查询执行散列连接?由于特权限制,我无法创建表格。

2 个答案:

答案 0 :(得分:0)

您的设置中的db2level是什么?如果它是DB2 v9或更早版本,那么优化器甚至不考虑HSJOIN的一个原因是有问题的查询包含表达式上的连接谓词。在这种情况下,优化配置文件不是一种选择。使用会话表是个好主意。

从DB2 v10开始,HSJOIN也适用于表达式连接。因此,优化器开始考虑它。但最终决定仍以成本为基础。估计更便宜的计划胜出。

参考文献:

v97 info

v10 info

答案 1 :(得分:0)

从根本上说,你不是在比较苹果和苹果。在您的第一个场景中,构建表a和b正在作为查询的一部分完成,并且优化器将此工作作为其“整个连接策略”的一部分。由于它必须在内存中构建表,因此NLjoin扫描它们不是太多额外的工作。在第二种情况下,优化器会考虑两个具有等价谓词的现有表之间的连接,并发现HSjoin是可行的方法。