2

我正在优化 DB2 数据库的一些查询。它们中的大多数都运行良好,但是一些返回数据集相当大(最多 30k 行左右)的部分给我带来了一些麻烦。这些查询没有什么特别复杂的。他们从大约十几个连接中选择了大约 15 个不同的列,其中包括一些内连接和左连接。有一些 IN 子句可以使用参数和子查询来减少数据集。这没什么特别的。

我一直在查看一些索引,但运气不佳。问题是,在尝试强制使用未使用的新索引时,我偶然发现了 DB2 中的一个绝妙技巧:谓词中的无操作 COALESCE 可以潜在地降低成本和运行时间。

基本上,它是这样工作的:

SELECT ...
FROM A
JOIN B
ON A.ID1 = B.ID1
AND A.ID2 = B.ID2
--More inner and left joins--
WHERE
B.TYPE_CODE IN (:parameter)
AND A.X IN (--subquery--)
AND
COALESCE(B.TYPE_CODE,B.TYPE_CODE) = B.TYPE_CODE

从逻辑的角度来看,COALESCE 什么都不做,并且 B.TYPE_CODE 永远不会为空。但是,这会欺骗 DB2 优化器来估计较少的行数,此处解释:

http://www-01.ibm.com/support/docview.wss?uid=swg21259831

对于 TABLE B,TYPE_CODE 列有大约 15 个不同的可能值,分布不均匀。那里大约有 270 万行,A 中大约有 900k 行。因此,B 中的 ID1/ID2 列可能重复相同的值对多达 15 次或仅出现一次。:parameter 不超过四个值。

奇怪的是 COALESCE 语句将查询时间缩短了一半。在检查解释计划时,我注意到 A 上的几个表扫描变成了索引扫描,这可能是由于返回行的估计值较低,使得索引扫描对优化器来说是可行的。我一直在挖掘并试图找到一个可能的原因。RUNSTATS 是最近在这些表上运行的,SYSCAT.COLDIST 表中有一些非常新的数据,如果我手动检查计数,至少在值的 1% 以内。我确实注意到它没有包含 TYPE_CODE 列中的所有值,但是缺少的值很少发生,并且从 IN 子句中省略稀有值对查询时间没有实际影响。我在其他列上尝试过 COALESCE,但效果不同。

我能想到的唯一解释是一些统计数据是陈旧的、糟糕的、过时的等,但如果我知道在哪里看这一点,那就太糟糕了。我可以说没有列组统计信息,但我没有足够的知识来判断这是否会有所作为。

我不想将 COALESCE 声明投入生产,因为它有点老套,而且更像是解决更深层次问题的创可贴,而不是解决方案本身。在我看来,DB2 似乎高估了将在该连接中返回的行数,但如果我知道原因,那该死的。我希望其他具有 DB2 经验的人能够对此有所了解。

4

1 回答 1

0

I'm wondering why you have in (:parameter), would parameter not be a single value?

Do you get better performance from separate OR clauses than the IN?

I'm targeting the IN clause because it apparently can give performance issues (see: Performance of "in" condition query in db2 ).

于 2013-08-29T05:08:17.810 回答