我正在处理对基于用户选择多个值而组装的登录页面的一些查询,并将它们发送到DB2数据库。我正在尝试将它们调整到尽可能快,并获得一些好的结果。但是,有一些查询具有一些非常难看的执行时间,如10秒左右。我一直在研究解释计划,并且看到了一些奇怪的东西。
对于初学者来说,这些查询非常简单。有几个内部连接,几个左连接和一些过滤条件。他们正在加入一些非常庞大的表(有些拥有约270万行)并返回一些非常强大的数据集(最多30k行左右,可能是15行左右)。问题是,在检查解释计划时,我看到了一个非常奇怪的事情。这是一个FETCH操作,占查询成本的1/3到1/2。此FETCH与以下连接相关:
SELECT ...
FROM A
JOIN B
ON B.ID1 = A.ID1
AND B.ID2 = A.ID2
WHERE
B.FIELD IN (:parameter --No more than four strings in here)
A.ID1和2是A的主键,但在B中不是唯一的.B.FIELD总共包含十几个不同的字符串值,但该表大约有270万行。我所看到的是B上的FETCH操作,它包含一个RIDSCN,它本身包含B.FIELD IN子句中每个参数的一个排序操作,每个参数包含一个B上的索引扫描。令人担心的是FETCH的时间长度手术正在进食,特别是考虑到这是十几次加入之一。
我一直在挖掘索引,并且有一些理论,但我不确定问题在哪里,我不能自己应用任何索引,只是请求它们,所以这有点痛苦。 A在ID1和ID2上编入索引。 B也在ID1和ID2上编入索引。在这些SORT操作中,有一个单独的索引用于B.FIELD(在B中还包含一些其他字段)。但是,B没有ID1,ID2,FIELD的索引。创建此索引可能会减少我在FETCH操作中看到的次数吗?我不完全确定这是由于缺少适当的索引或只是表的大小和列中数据的性质。我已经在几张桌子上请求runstats,看看他们是否会从重组中获益,但如果没有这样做,我希望有些人可能会有所帮助。我对索引的应用和细微差别仍然有点新鲜。
编辑:这是解释计划的相关部分。值得注意的是,这是解释计划树中的第一个操作之一(如在一系列NLJOIN,HSJOIN等之后):
SCHEMA.B FETCH 35.1 % 177046.0625
RIDSCN 0.0 % 5716.63037109375
SORT 0.0 % 5257.94189453125
B.INDEX IXSCAN 1.0 % 5018.35009765625
SORT 0.0 % 385.5107116699219
B.INDEX IXSCAN 0.1 % 374.5053405761719
SORT 0.0 % 50.442073822021484
B.INDEX IXSCAN 0.0 % 50.34944152832031
SORT 0.0 % 22.738037109375
B.INDEX IXSCAN 0.0 % 22.73009490966797
问题是,我有一些其他查询在IN子句中没有显示这种成本,即使返回数千行。使用一个连接的三分之一查询成本似乎过多。就像我之前说的那样,也许它与这个特定的表甚至是额外的连接有更多关系,但我真的想找到一种方法来削减这个数字。
答案 0 :(得分:0)
我不确定这应该算作答案,但至少有两种其他方式可以表达你的意图。
WHERE B.FIELD = :param1 OR B.FIELD = :param2 ...
SELECT ...
WHERE B.FIELD = :param1
UNION ALL
SELECT ...
WHERE B.FIELD = :param2
...
多年来我一直与DB2查询优化器失去联系。它可能以不同方式处理这些逻辑上等效的语句可能不是一件好事。在过去,如果查询优化器为两个逻辑上等效的查询生成两个不同的执行计划,则至少有一个产品将其视为错误。 (Rdb?Ingres?不记得了。)
我不喜欢以这种方式游戏优化器。今天在IN谓词中表现良好的可能会因下个月的更新而瘫痪。
就索引的构成而言,我希望开发人员能够将其作为其工作的常规部分。如果您的雇主不会给您使用临时dbms,那么您可以考虑这些替代方案。 (我不是建议你做任何违反雇主政策的事情。这是一个被解雇的快捷方式。)
不要将公司数据移到公司外面。
如果您无法解决创建索引等问题,请使用缓慢的,官方认可的DBA请求。