【发布时间】:2013-03-26 21:57:40
【问题描述】:
我正在处理基于用户选择多个值的登录页面的一些查询,并将它们发送到 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、FIEL 的索引。创建此索引是否会减少我在该 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 子句中显示这种成本,即使返回数千行也是如此。为一个连接使用三分之一的查询成本似乎过高。就像我之前说的,也许它与这个特定的表甚至额外的连接有更多关系,但我真的很想找到一种方法来减少这个数字。
【问题讨论】:
-
“B.FIELD 使用了一个单独的索引(它还包含 B 中的一些其他字段)” B.FIELD 是其中的第一列吗?单独的索引?如果不是,则在评估
B.FIELD IN (...)时可能不会使用该索引。 -
它是该索引中的第一个字段,后跟两个 ID 字段,作为 B 的主键,尽管在此查询中没有使用它们。
-
你能编辑你的问题,然后粘贴 EXPLAIN 的输出吗?我认为排序操作对于 DB2 中的 IN 谓词是正常的。 (对行标识符进行排序可以提高 I/O 的效率。)
-
这个查询的执行速度有多快:
select id1, id2 from B where FIELD in ( <your list > )?又返回了多少行?