0

我正在处理一些登陆页面的查询。该页面将为用户提供多种搜索选项。查询将根据用户选择的内容由不同的部分构成,并将其发送到 DB2 数据库。总而言之,有超过 100 个独特的查询。我正在努力降低性能,但我的性能有点太长了。基本结构是这样的:

SELECT ...
FROM
TABLE A
--A few joins and a few left joins--
WHERE A.FIELD1 IS NOT NULL
  AND A.FIELD2 IN (:parameter) --No more than two values in here
  AND (
        A.FIELD3 IN ('ONE', 'TWO')
    OR (A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y)
  )
  AND A.FIELD5 IN (uncorrelated subquery, potentially returns over 1k values, usually less)

FIELD2 和 3 被选中,而其他的仅被过滤。FIELD5 用于连接,但这与使用子查询的过滤无关。问题来自 (X OR Y) 子句。查询现在执行大约需要 3 秒。如果我删除 OR 子句中的任何一个条件,它会在不到十分之一的时间内执行。奇怪的是,将它们都删除会使它恢复大约 3 秒,这没有多大意义,因为它似乎并没有增加数据集的大小。带有 OR 子句或没有这两个条件的解释计划几乎相同,但它似乎不是索引问题,因为它似乎在相关表上命中相同的索引。在这两种情况下,最大的成本都来自最外层的 NLJOIN。从 OR 子句中删除一个条件(所以它'

我已经尝试使用子查询和联合来解决这个问题,甚至在两个查询之间使用 UNION ALL 仅区分该子句(这确实帮助了这个实例一点,但显着减慢了其他查询),但似乎没有任何帮助执行时间处理时间。我不能真正发布完整的详细信息,因为查询非常庞大,但希望这足以让这个想法得到理解。我知道 OR 子句有时可以将优化器抛出一个循环,所以我想关于避免有问题的 OR 子句或将优化器推向更好方向的一般建议将不胜感激,即使它不是直接针对此示例。

4

3 回答 3

1

您可以尝试使用case声明。

代替

AND ( A.FIELD3 IN ('ONE', 'TWO') 
 OR (A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y))

采用

AND CASE WHEN A.FIELD3 IN ('ONE', 'TWO') THEN 1 
     WHEN A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y THEN 1 ELSE 0 END = 1
于 2013-04-03T18:09:18.527 回答
0

这可能看起来很极端,但你可以将两个快速版本结合在一起......一个与这条线

AND A.FIELD3 IN ('ONE', 'TWO') 

和一个

A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y)
于 2013-04-03T18:11:10.050 回答
0

尝试:

SELECT ...
FROM
TABLE A
--A few joins and a few left joins--
WHERE A.FIELD1 IS NOT NULL
  AND A.FIELD2 IN (:parameter) 
  AND A.FIELD3 IN ('ONE', 'TWO', 'THREE', 'FOUR')
  AND (A.FIELD3 IN ('ONE', 'TWO') OR A.FIELD4 BETWEEN :x AND :y)
  AND A.FIELD5 IN (uncorrelated subquery)
于 2013-04-03T18:33:22.343 回答