供参考:可精简的
#1 楼
使查询不可保留的最常见的方法是在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内包含一个函数会导致查询不可保留吗?
–迈克·贝利(Mike Bailey)
2012年6月22日12:26
有些数据库引擎(Oracle,PostgreSQL)支持表达式索引,不知道吗?
– Craig
2014年3月27日14:50
是否会选择一个更好的WHERE((FullName ='Ed Jones')或(FullName IS NULL))版本... FROM ... WHERE FullName ='Ed Jones'UNION SELECT ... FROM ... WHERE FullName一片空白?曾经有一个优化专家告诉我,在where子句中使用OR可以取消查询的参数..?
–High Plains Grifter
15年11月9日在9:30
@HighPlainsGrifter,您应该在该查询上使用UNION ALL-联合具有隐式的distinct,这使查询的成本比必须互斥数据集时所需的成本高得多
–德文·拉莫特(Devin Lamothe)
18年5月24日在18:02
@BradC在MSSQL 2016中,Select ... WHERE isNull(FullName,'Ed Jones')='Ed Jones'和Select ... WHERE((FullName ='Ed Jones')或(FullName)之间没有执行计划差异一片空白))。他们都使用FullName上的索引并进行索引查找。
–已压缩
18-09-19在7:53
#2 楼
不要执行以下操作:WHERE Field LIKE '%blah%'
这会导致表/索引扫描,因为LIKE值以通配符开头。
Don不这样做:
WHERE FUNCTION(Field) = 'BLAH'
这将导致表/索引扫描。
数据库服务器将必须针对每个数据库评估FUNCTION()表中的第二行,然后将其与“ BLAH”进行比较。
如果可能,请相反进行操作:
WHERE Field = INVERSE_FUNCTION('BLAH')
这将运行INVERSE_FUNCTION ()一次针对该参数,仍将允许使用索引。
评论
您关于翻转函数的建议实际上仅在函数往返数据时才有效(这意味着f(f(n))= n)。
–亚当·罗宾逊(Adam Robinson)
09年4月28日在20:16
真正。我考虑过添加INVERSE_FUNCTION,但不想造成混淆。我会改变它。
–海滩
09年4月28日在20:17
#3 楼
在这个答案中,我假设数据库具有足够的覆盖索引。有关此主题的问题很多。很多时候,查询的可存储性取决于相关索引的临界点。引爆点定义了在将一个表或结果集连接到另一个表或结果集时查找和扫描索引之间的差异。当然,一次查找比扫描整个表要快得多,但是当您必须查找很多行时,扫描可能更有意义。
因此,当优化程序期望一个表的结果行数小于下一个表的可能索引的临界点时,SQL语句更易处理。
您可以在此处找到详细的帖子和示例。
#4 楼
对于被认为是可操作的操作,仅使用现有索引是不够的。在上面的示例中,在where子句中对索引列添加函数调用仍然很可能会利用已定义的索引。它将再次“扫描”该列(索引)中的所有值,然后消除那些与提供的过滤器值不匹配的值。对于行数较高的表,它仍然不够高效。真正定义可保存性的是使用二进制搜索方法遍历b树索引的查询能力,该方法依赖于对排序项数组进行半集消除。在SQL中,它将作为“索引查找”显示在执行计划上。
评论
+1为“可燃气”。这就是我今天的话。 :-p我还可以补充亚当的回答,即在大多数情况下,每个DB引擎的信息量都是极其特殊的。
SARG =搜索参数。有趣的是:德语中的“ SARG”意为“棺材”,所以当人们谈论“可食用的”时,我总是要微笑-可以放在棺材里吗? :-)
可持久性取决于您的环境。 MySQL文档记录在这里:dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
使用自由文本字段代替“查找表”也违背了使查询可修改的精神。用户输入自由文本(例如镇名)时拼写错误,而查找表则迫使用户选择正确拼写的条目。值得稍加麻烦,因为它可以正确地索引,而不是在谓词中使用LIKE'%...%'。