具有Exists / In的几层嵌套子查询,性能最佳?

时间:2013-03-12 18:22:14

标签: sql db2 nested subquery

我正在为搜索功能进行一些相当大的查询。有许多不同的输入,因此查询非常大。它已经发展到嵌套子查询2层深的地方。性能已成为将返回大型数据集并且可能需要筛选大量记录的问题。比较少的那些表现不错,但其中一些变得非常糟糕。数据库是DB2并且具有所有必需的索引,因此不应该成为问题。我想知道如何最好地编写/重写这些查询来执行,因为我不太确定优化器将如何处理它。我显然无法在这里抛弃整个事情,但这是一个例子:

Select A, B 
from TableA
      --A series of joins--
WHERE TableA.A IN (
      Select C 
      from TableB
              --A few joins--
      WHERE TableB.C IN (
              Select D from TableC
              --More joins and conditionals--
              )
       )

还有很多条件,其中绝大多数都是简单的平等。你明白了。子查询不向初始查询提供任何数据。它们仅用于过滤结果。我早期遇到的一个问题是,后端被编写为包含许多部分查询字符串,这些字符串被汇总到最终查询中(由于搜索选项而有100多种可能的组合,编写查询根本不可行)对于每个),这使整个方法有点复杂。我想知道EXISTS而不是IN可能会帮助一个或两个级别,或者另一堆连接而不是子查询,或者可能在TableC的初始查询之上使用WITH等等。我肯定想要消除瓶颈并且会欣赏任何人可能对如何处理此事的反馈。

我还应该补充说,两个子查询中都有潜在的联合。

2 个答案:

答案 0 :(得分:0)

可能有助于使用内部联接。

Select A, B
from TableA
  inner join TableB on TableA.A = TableB.C
  inner join TableC on TableB.C = TableC.D

数据库是为连接而设计的,但优化器可能不知道它可以使用索引进行子查询。相反,它可能会尝试运行子查询,将结果保存在内存中,然后进行线性搜索以评估每个记录的IN运算符。

现在,您说您拥有所有必要的索引。暂时考虑一下。

如果一个可选条件是TableC.E ='E'而另一个可选条件是TableC.F ='F', 那么两者的查询都需要字段TableC.E AND TableC.F上的索引。今天许多年轻的程序员认为他们可以在TableC.E上有一个索引,在TableC.F上有一个索引,这就是他们所需要的。实际上,如果查询中同时包含两个字段,则需要在两个字段上都有索引。

因此,对于100多种组合,“所有必要的索引”可能需要100多个索引。

现在TableC.E上的索引,TableC.F可以在具有TableC.E条件且没有TableC.F条件的查询中使用,但是当存在TableC.F条件且没有TableC时无法使用。 E条件。

数以百计的指数?我该怎么办?

在实践中它并没有那么糟糕。假设你有N个可选条件,它们都在where子句中。组合的数量是2到n,或者对于数百种组合,N是组合数的log2,其在6和10之间。此外,这些log2条件分布在三个表中。有些数据库支持多个表索引,但我不确定DB2是否支持,所以我坚持使用单表索引。

所以,我要说的是,对于TableC.E和TableC.F示例来说,仅仅使用以下索引是不够的:

TableB ON C
TableC ON D
TableC ON E
TableC ON F

首先,优化器必须选择要使用的最后三个索引中的一个。更好的是在最后两个索引中包含D字段,这给了我们

TableB ON C
TableC ON D, E
TableC ON D, F

这里,如果查询中没有字段E和F,它仍然可以在D上编制索引,但如果查询中有任何一个,它可以在D和另一个字段上编制索引。

现在假设您有10个字段的索引,这些字段可能在查询中,也可能不在查询中。为什么索引中只有一个字段?为什么不按查询可能性的降序添加其他字段?

在规划索引时考虑一下。

答案 1 :(得分:0)

我发现“IN”谓词适用于小子查询,而“EXISTS”适用于大子查询。 尝试使用“EXISTS”谓词执行大查询。

SELECT A, B 
FROM TableA
WHERE EXISTS (
      Select C 
      FROM TableB
      WHERE TableB.C = TableA.A)