DBMS 一般采用自下而上的顺序解析 WHERE 子句,根据这个原理,表连接最好写在其他 WHERE 条件之前,那些可以过滤掉最大数量记录。
比如下面的 SQL 语句性能较差:
<font size="2" style="font-weight: normal;">SELECT * FROM T_Person WHERE FSalary > 50000 AND FPosition='MANAGER' AND 25 < (SELECT COUNT(*) FROM T_Manager WHERE FManagerId=2);</font>
复制代码
我们将子查询的条件放到最前面,下面的 SQL 语句性能比较好:
<font size="2" style="font-weight: normal;">SELECT * FROM T_Person WHERE 25 < (SELECT COUNT(*) FROM T_Manager WHERE FManagerId=2) AND FSalary > 50000 AND FPosition='MANAGER';</font>
6) 用 Where 子句替换 HAVING 子句避免使用 HAVING 子句,因为 HAVING 只会在检索出所有记录之后才对结果集进行过滤。如果能通过 WHERE 子句限制记录的数目,那就能减少这方面的开销。HAVING 中的条件一般用于聚合函数的过滤,除此而外,应该将条件写在 WHERE 子句中。
10) 避免在索引列上使用计算
在 WHERE 子句中,如果索引列是计算或者函数的一部分,DBMS 的优化器将不会使用索引而使用全表扫描。
11) 用 UNION ALL 替换 UNION
当 SQL 语句需要 UNION 两个查询结果集合时,即使检索结果中不会有重复的记录,如果使用 UNION 这两个结果集同样会尝试进行合并,然后在输出最终结果前进行排序。 因此,如果检索结果中不会有重复的记录的话,应该用 UNION ALL 替代 UNION,这样效率就会因此得到提高。
12) 避免隐式类型转换造成的全表扫描
13) 防止检索范围过宽
如果 DBMS 优化器认为检索范围过宽,那么它将放弃索引查找而使用全表扫描。下面是几种可能造成检索范围过宽的情况: 使用 IS NOT NULL 或者不等于判断,可能造成优化器假设匹配的记录数太多。 使用 LIKE 运算符的时候,”a%”将会使用索引,而”a%c”和”%c”则会使用全表扫描,因此”a%c”和”%c”不能被有效的评估匹配的数量。