我一直在阅读并发现使用LIKE会导致查询速度大幅下降。
一位同事建议我们使用
Select Name
From mytable
a.Name IN (SELECT Name
FROM mytable
WHERE Name LIKE '%' + ISNULL(@Name, N'') + '%'
GROUP BY Name)
代替
Select Name
From mytable
a.Name LIKE '%' + ISNULL(@Name, N'') + '%'
现在我不是SQL专家,我不太了解这些陈述的内部工作原理。这是一个更好的选择,值得为每个类似的声明键入一些额外的字符吗?是否有更好的(更容易打字)替代方案?
答案 0 :(得分:9)
要解决几个性能问题......
不要将子查询用于可以在不需要引用同一个表的其他副本的情况下完成的条件。如果由于使用聚合函数(MAX,MIN等)而需要表副本中的数据是可以接受的,尽管分析函数(ROW_NUMBER,RANK等)可能更容易(假设支持)。
如果您的参数为NULL,这意味着您想要比较的列的任何值,请不要包含过滤条件。这样的陈述:
WHERE a.Name LIKE '%' + ISNULL(@Name, N'') + '%'
...保证优化器必须比较name
列的值,不管是否为通配符。更糟糕的是,在LIKE
的情况下,评估左侧的通配符可确保在搜索的列中存在索引时无法使用索引。
表现更好的方法是:
IF @Name IS NOT NULL
BEGIN
SELECT ...
FROM ...
WHERE a.name LIKE '%' + @Name + '%'
END
ELSE
BEGIN
SELECT ...
FROM ...
END
表现良好的SQL就是要根据您的需要定制。这就是你should be considering dynamic SQL when you have queries with two or more independent criteria的原因。
当您检查文本数据中是否存在字符串时,LIKE
运算符在搜索文本时效率不高。 Full Text Search (FTS) technology旨在解决这些缺点:
IF @Name IS NOT NULL
BEGIN
SELECT ...
FROM ...
WHERE CONTAINS(a.name, @Name)
END
ELSE
BEGIN
SELECT ...
FROM ...
END
我同意LittleBobbyTables - 该解决方案最终依赖于检查所有替代方案的查询/执行计划,因为表格设计&数据会影响优化程序的决策和性能。在SQL Server中,具有最低子树的算法效率最高,但如果不维护表统计信息和索引,它可以随时间变化。
答案 1 :(得分:8)
只需比较执行计划,您就应该看到差异。
我没有您的确切数据,但我针对我的SQL Server 2005数据库运行了以下查询(是的,这是书呆子):
SELECT UnitName
FROM Units
WHERE (UnitName LIKE '%Space Marine%')
SELECT UnitName
FROM Units
WHERE UnitName IN (
(SELECT UnitName FROM Units
WHERE UnitName LIKE '%Space Marine%' GROUP BY UnitName)
)
以下是我的执行计划结果:
您的同事建议在我的查询中添加嵌套循环和第二次聚簇索引扫描,如上所示。您的里程可能会有所不同,但一定要检查执行计划,看看他们的比较方式。我无法想象它会如何更有效率。
答案 2 :(得分:4)
除非IIQR是某个较小的表,它以某种方式对名称进行索引(并且不是从一开始就在这里查询的原始表),否则我看不出那个更长的版本会有什么帮助;它正在做同样的事情,但只是添加一个额外的步骤来创建一组在IN中使用时的结果。
但即使IIQR是一个较小的'索引'表,我也会怀疑。我想看到有关数据库的更多信息,以及查询计划的最终结果。
LIKE会对查询性能产生负面影响,因为它通常需要进行表扫描 - 物理加载每个记录的相关字段并搜索相关文本。即使该字段被索引,也可能是这种情况。但如果您需要做的是在字段内的任何可能位置搜索部分文本,则可能无法绕过它。
但取决于相关表格的大小;它根本不重要。
对于你,但是;我建议保持简单是最好的。除非你真的知道复杂查询的整体效果会对性能有什么影响,否则很难尝试决定采用哪种方式。