是什么让SQL语句变得可思议?

时间:2009-04-28 19:59:05

标签: sql-server performance

根据定义(至少从我所见过的),sargable意味着查询能够让查询引擎优化查询使用的执行计划。我已经尝试过查找答案,但似乎没有太多关于主题的内容。所以问题是,什么做或不做一个SQL查询sargable?任何文件都将不胜感激。

供参考:SARGable

4 个答案:

答案 0 :(得分:231)

查询 non-sargable 的最常见的事情是在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()) 

答案 1 :(得分:75)

不要这样做:

WHERE Field LIKE '%blah%'

这会导致表/索引扫描,因为LIKE值以通配符开头。

不要这样做:

WHERE FUNCTION(Field) = 'BLAH'

导致表/索引扫描。

数据库服务器必须针对表中的每一行评估FUNCTION(),然后将其与'BLAH'进行比较。

如果可能,请反向执行:

WHERE Field = INVERSE_FUNCTION('BLAH')

这将对参数运行一次INVERSE_FUNCTION()并仍然允许使用索引。

答案 2 :(得分:9)

在这个答案中,我假设数据库有足够的覆盖索引。有关this topic的足够问题。

很多时候,查询的sargability是由相关索引的引爆点决定的。临界点定义了在将一个表或结果集连接到另一个表或结果集时搜索和扫描索引之间的差异。一次搜索当然要比扫描整个表格快得多,但是当你不得不寻找很多行时,扫描就会更有意义。

因此,当优化器期望一个表的结果行数小于下一个表上可能索引的临界点时,SQL语句更具可搜索性。

您可以找到详细的帖子和示例here

答案 3 :(得分:3)

对于一个被认为是sargable的操作,仅仅能够使用现有索引是不够的。在上面的示例中,对where子句中的索引列添加函数调用仍然很可能会利用已定义的索引。它将“扫描”也从该列(索引)中检索所有值,然后消除与提供的过滤器值不匹配的值。对于行数较多的表,它仍然不够高效。 真正定义sargability的是使用二进制搜索方法遍历b-tree索引的查询能力,该方法依赖于已排序项目数组的半集消除。在SQL中,它将作为“索引搜索”在执行计划中显示。