我们遇到了一个问题,我们希望 Stack Overflow 的好人可以帮助我们。我们正在运行 SQL Server 2008 R2 并且在查询需要很长时间才能在大约 100000 行的中等数据集上运行时遇到问题。我们使用 CONTAINS 来搜索 xml 文件,并在另一列上使用 LIKE 以支持前导通配符。
我们使用以下运行大约需要 35 秒的小查询重现了该问题:
SELECT something FROM table1
WHERE (CONTAINS(TextColumn, '"WhatEver"') OR
DescriptionColumn LIKE '%WhatEver%')
查询计划:
如果我们将上面的查询修改为使用 UNION,运行时间将从 35 秒下降到 < 1 秒。我们希望避免使用这种方法来解决问题。
SELECT something FROM table1 WHERE (CONTAINS(TextColumn, '"WhatEver"')
UNION
(SELECT something FROM table1 WHERE (DescriptionColumn LIKE '%WhatEver%'))
查询计划:
我们使用 CONTAINS 搜索的列是一个类型为 image 的列,由大小从 1k 到 20k 的任何 xml 文件组成。
关于为什么第一个查询如此缓慢,我们没有好的理论,所以我们希望这里有人能就此事发表一些明智的看法。据我们所知,查询计划没有显示任何异常。我们还重建了索引和统计信息。
有什么明显明显的东西是我们忽略的吗?
在此先感谢您的时间!
最佳答案
您为什么使用 DescriptionColumn LIKE '%WhatEver%'
而不是 CONTAINS(DescriptionColumn, '"WhatEver"')
?CONTAINS
显然是一个全文谓词,将使用 SQL Server 全文引擎来过滤搜索结果,但是 LIKE
是一个“正常”的 SQL Server 关键字,因此 SQL Server 不会使用全文引擎来协助此查询 - 在这种情况下,因为 LIKE
术语以通配符开头 SQL Server 将无法使用任何索引来帮助查询,这很可能会导致表扫描和/或比使用全文引擎更差的性能。
如果没有执行计划,很难判断,但是我对发生的事情的猜测是:
UNION
查询的变体是对 table1
执行表扫描- 表扫描并不快,但是因为表中的行相对较少,所以它的执行速度并不慢(与 35 秒基准相比)。 OR
查询的变体 SQL Server 首先使用全文引擎根据 CONTAINS
进行过滤。然后继续对结果中的每个匹配行执行 RDI 查找以根据 LIKE
进行过滤。谓词,但是由于某种原因,SQL Server 大大低估了行数(这可能发生在某些类型的谓词中),因此继续执行数以千计的 RDI 查找,结果非常慢(表扫描会快得多) )。 要真正了解正在发生的事情,您需要获得一个查询计划。
关于sql - 涉及 CONTAINS 和 OR 的慢速 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6534322/