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

DFo*_*k42 243 sql-server performance

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

供参考:SARGable

Bra*_*adC 243

使查询不可搜索的最常见的事情是在where子句中的函数内包含一个字段:

SELECT ... FROM ...
WHERE Year(myDate) = 2008
Run Code Online (Sandbox Code Playgroud)

SQL优化器无法在myDate上使用索引,即使存在索引也是如此.它实际上必须为表的每一行评估此函数.使用起来好多了:

WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'
Run Code Online (Sandbox Code Playgroud)

其他一些例子:

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()) 
Run Code Online (Sandbox Code Playgroud)

  • 在GROUP BY中包含一个函数会导致查询变为不可搜索吗? (7认同)
  • 更好的版本`WHERE((FullName ='Ed Jones')OR(FullName IS NULL))```SELECT ... FROM ... WHERE FullName ='Ed Jones'UNION SELECT ... FROM .. .WHERE FullName IS NULL`?我曾经被优化人员告知在where子句中使用OR可以解析查询..? (3认同)
  • *一些*数据库引擎(Oracle、PostgreSQL)支持表达式索引,不知道吗? (2认同)
  • @HighPlainsGrifter 您应该在该查询上使用 UNION ALL - union 具有隐式不同,这使得查询比您必须互斥数据集时所需的成本高得多 (2认同)
  • @BradC 在 MSSQL 2016 中,`Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'` 和 `Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))`。它们都使用 FullName 上的索引并进行索引查找。 (2认同)

bea*_*ach 77

不要这样做:

WHERE Field LIKE '%blah%'
Run Code Online (Sandbox Code Playgroud)

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

不要这样做:

WHERE FUNCTION(Field) = 'BLAH'
Run Code Online (Sandbox Code Playgroud)

这会导致表/索引扫描.

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

如果可能的话,反过来做:

WHERE Field = INVERSE_FUNCTION('BLAH')
Run Code Online (Sandbox Code Playgroud)

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

  • 真正.我考虑过添加INVERSE_FUNCTION,但不想让人感到困惑.我会改变它. (5认同)
  • 翻转函数的建议实际上只有在函数往返数据时才起作用(意味着f(f(n))= n). (4认同)

Dri*_*jck 9

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

很多时候,查询的可争夺性由相关索引的临界点决定.临界点定义了在将一个表或结果集连接到另一个表或结果集时搜索和扫描索引之间的差异.一次搜索当然要比扫描整个表格快得多,但是当你必须寻找大量行时,扫描可能更有意义.

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

您可以在此处找到详细的帖子和示例.


小智 5

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