我有一个非常复杂的查询,它有时会非常缓慢地返回结果。从一开始就很清楚,罪魁祸首是与全文搜索有关的 WHERE 子句的一部分。所以我将其隔离并进行了测试。该测试导致确定它何时发生,但到目前为止我未能弄清楚如何修复它。这是问题所在:
我需要根据用户想要执行的操作筛选一个、两个或三个全文索引列。因为似乎 CONTAINS 谓词中的列列表不能作为变量提供,所以我能想到的下一个最好的办法是使用一些标准的布尔逻辑,如下所示:
(((@SearchInName = 0 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 0) OR @SearchExpression = '""')
OR (@SearchInName = 1 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 0 AND CONTAINS(ProductName, @SearchExpression))
OR (@SearchInName = 0 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 0 AND CONTAINS(ProductShortDescr, @SearchExpression))
OR (@SearchInName = 0 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 1 AND CONTAINS(ProductDescrHTML, @SearchExpression))
OR (@SearchInName = 1 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 0 AND CONTAINS((ProductName, ProductShortDescr), @SearchExpression))
OR (@SearchInName = 1 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 1 AND CONTAINS((ProductName, ProductDescrHTML), @SearchExpression))
OR (@SearchInName = 0 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 1 AND CONTAINS((ProductShortDescr, ProductDescrHTML), @SearchExpression))
OR (@SearchInName = 1 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 1 AND CONTAINS((ProductName, ProductShortDescr, ProductDescrHTML), @SearchExpression))
只要实际的有效条件与最后一个 OR 部分匹配,那就可以了,并且可以按预期(快速)工作。所以在上面的例子中,当@SearchInName = 1 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 1 时(用户想要搜索所有 3 列)。如果将其他条件放在此代码块的最后,其他条件也会快速返回。但是,一旦实际有效条件高于上一个,似乎它后面的所有 CONTAINS 语句也会运行(尽管不一定包含在结果中,这是正确的),这将执行时间从 1s 到 6秒或更多,这取决于有效语句的高度,因此后面还有多少其他 CONTAINS 谓词。
我知道执行顺序并不总是由实际代码给出,并且在 SQL 优化之后,由于它的原因,一些短路可能无法按设计工作,这似乎就是这种情况。通常的建议是使用 CASE 语句来确保顺序,但不幸的是,CONTAINS 语句在 CASE 语句中似乎并不令人满意。
所以我想我可能有点知道它为什么会发生(SQL 优化),但无法弄清楚如何实际解决这个问题。任何人都可以帮忙吗?