SQL查询优化(条件评估方向)

SQL查询优化(条件评估方向),sql,query-optimization,Sql,Query Optimization,假设我有一本26000个单词的字典,每个字母表有1000个单词。 如果我想找到所有带有“e”的单词,我会写: SELECT * FROM dict WHERE word LIKE '%e%'; 如果我想将其简化为以“a”开头的单词,我可以改变类似的条件,或者我可以这样做: SELECT * FROM dict WHERE word LIKE '%e%' AND id < 1000; 很多单词中都有字母“e”,因此如果从左到右对条件进行求值,则返回true只会

假设我有一本26000个单词的字典,每个字母表有1000个单词。 如果我想找到所有带有“e”的单词,我会写:

SELECT * 
  FROM dict 
 WHERE word LIKE '%e%';
如果我想将其简化为以“a”开头的单词,我可以改变类似的条件,或者我可以这样做:

SELECT * 
  FROM dict 
 WHERE word LIKE '%e%' 
   AND id < 1000;
很多单词中都有字母“e”,因此如果从左到右对条件进行求值,则返回true只会不满足第二个要求,但如果从右到左对条件进行求值,我希望得到更快的结果


我的问题是,将id<1000作为第一个条件还是第二个条件更好,或者这取决于数据库的类型。

条件的位置无关,如果适用,将需要相同数量的扫描。它们不是按顺序解析的——优化器根据表统计信息和索引(如果存在)确定应用的内容和时间。这些统计数据会发生变化,并且可能会过时,这就是为什么维护非常重要的原因

假设id<1000等于

从dict中选择*,其中的单词类似于“a%”

如果以这种方式设计数据库,它将违反第一个标准形式,具体来说:没有对行进行从上到下的排序。
从技术上讲,没有一种方法可以确保这种排序是有效的,特别是如果您想在设置初始状态后添加一个以“a”开头的单词。

现代关系数据库管理系统的关键设计原则之一是您,即用户,对于RDBMS在硬盘上实际存储数据的方式没有真正的控制权或发言权。这意味着您不能假设数据是按字母顺序存储在驱动器上的a,或者在检索数据时,数据将按字母顺序检索。要百分之百地确定你得到了你想要的数据,唯一的办法就是清楚地说出你想要的方式,而其他任何事情都是假设有一天你会被炸得面目全非

为什么这很重要?因为您的查询假设您将获得的数据是按字母顺序排列的,从A开始,然后向上。假设情况是一致的,那么A对A呢?有前导空格或数字的吗?不同的系统以不同的方式处理不同的数据。。。要解决这一问题非常简单,请添加ORDERBY子句,例如:

select * from dict where word like ("%e%") and id < 1000 order by word;

根据您的RDBMS和表上的任何索引,系统可以首先识别所有A字,然后仅对它们运行contains e检查。

尝试切换where子句条件,然后比较执行计划

这将向您展示差异,如果有的话,我想在这种情况下,它们将是相同的

底线是,在大多数情况下,这没有什么区别。
但是,它可以更改执行计划。

那么,简单的布尔检查id<1000肯定会比类似的%e%查询快,如果首先执行id比较,则不会执行该查询,除非在单独的线程中对其进行求值。执行计划将是相同的,无论是首先执行id检查还是最后执行id检查,因此那么先评估一下?因为如果评估的第一个条件失败,第二个条件肯定不会被评估…@j3frea:优化器根据表统计信息和索引(如果存在)确定应用的内容和时间。这些统计数据会发生变化,并且可能会过时,这就是为什么维护非常重要的原因。您的问题没有比这更明确的答案了。感谢OMG Ponies:optimizer确定+1这样做也会阻止您添加新行。好的,但问题是关于条件评估的顺序。答案是您的第二个条件无效,不应使用。尝试一个更好的例子,它不会违背关系数据库设计的核心。这只是一个愚蠢的答案。我简化了我的问题,因为事实上我有更复杂的东西,但复杂性是无关的。相关的是条件评估的顺序。如果我的一列是布尔值,并且我需要它是一个特定的值,该怎么办。去掉id条件并说property\u noon=TRUE。这是同一个问题。在这种情况下,我会说您需要确定您正在使用什么RDBMS,因为它们的计算和执行查询方式不同。阅读克瑞斯宾特的答案是迄今为止最好的。我只是告诉您,您的原始示例有缺陷,您应该将其更新为“property\u noon=TRUE”。在你这样做之前,没有人应该告诉你它将如何评估。正如我对N.Warfield所说的,我的实际问题是关于基于条件评估顺序的优化。不要在类似的子句上加括号/括号-它们仅用于操作顺序。在SQL中使用单引号进行字符串比较,而不是双引号…根据OMG Ponies,优化器根据表统计和索引确定应用的内容和时间
如果有的话。因此,换句话说,WHERE子句的顺序与性能无关。感谢这可能是真的,也可能不是真的,解释计划会告诉你答案。这里的一些链接表明这很重要,即使Tom Kyte不保证谓词顺序的改变也会生成相同的计划,请参见
select * from dict where left(word. 1) = "A" and word like ("%e%");