提问人:DForck42 提问时间:4/29/2009 最后编辑:Matt Johnson-PintDForck42 更新时间:5/12/2021 访问量:98244
是什么使 SQL 语句可优化?
What makes a SQL statement sargable?
问:
根据定义(至少从我所看到的情况来看),sargable 意味着查询能够让查询引擎优化查询使用的执行计划。我试着查找答案,但似乎没有太多关于这个主题的内容。那么问题来了,什么可以使 SQL 查询可优化,或者不能使 SQL 查询可优化?任何文件将不胜感激。
供参考:Sargable
答:
别这样:
WHERE Field LIKE '%blah%'
这会导致表/索引扫描,因为 LIKE 值以通配符开头。
别这样:
WHERE FUNCTION(Field) = 'BLAH'
这会导致表/索引扫描。
数据库服务器必须根据表中的每一行计算 FUNCTION(),然后将其与 'BLAH' 进行比较。
如果可能,请反向执行:
WHERE Field = INVERSE_FUNCTION('BLAH')
这将对参数运行 INVERSE_FUNCTION() 一次,并且仍然允许使用索引。
评论
使查询不可优化的最常见方法是在 where 子句的函数内包含一个字段:
SELECT ... FROM ...
WHERE Year(myDate) = 2008
SQL 优化器不能对 myDate 使用索引,即使存在索引也是如此。从字面上看,它必须为表的每一行计算此函数。使用起来要好得多:
WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'
其他一些例子:
Bad: Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Fixed: Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))
Bad: Select ... WHERE SUBSTRING(DealerName,4) = 'Ford'
Fixed: Select ... WHERE DealerName Like 'Ford%'
Bad: Select ... WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
Fixed: Select ... WHERE OrderDate < DateAdd(mm,-30,GetDate())
评论
GROUP BY
WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))
SELECT... FROM ... WHERE FullName = 'Ed Jones' UNION SELECT...FROM...WHERE FullName IS NULL
Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))
在这个答案中,我假设数据库有足够的覆盖索引。关于这个话题的问题已经够多了。
很多时候,查询的可优化性是由相关索引的临界点决定的。临界点定义了在将一个表或结果集联接到另一个表或结果集时查找和扫描索引之间的区别。当然,一次搜索比扫描整个表要快得多,但是当您必须查找大量行时,扫描可能更有意义。
因此,除其他事项外,当优化程序期望一个表的结果行数小于下一个表上可能索引的临界点时,SQL 语句更易于优化。
您可以在此处找到详细的帖子和示例。
要使操作被视为可优化,仅能够使用现有索引是不够的。在上面的示例中,在 where 子句中添加针对索引列的函数调用,仍然很可能会利用定义的索引。它将“扫描”,即从该列(索引)中检索所有值,然后消除与提供的筛选器值不匹配的值。对于行数较多的表,它仍然不够高效。 真正定义可优化性的是使用二进制搜索方法遍历 b 树索引的查询能力,该方法依赖于排序项目数组的半集消除。在 SQL 中,它将在执行计划中显示为“索引查找”。
上一个:T-SQL 拆分字符串
评论