要提高 SQL 语句的性能,就要保证 SQL 语句结构的合理,可能简单地改变查询条件的书写顺序,就能导致语句执行性能的大大不同。所以,我们在编写语句时,特别是编写 WHERE 子句时,安排好它的各组成部分的排序很重要。这些组成部分的排序是否
最佳是依赖于特定实现的处理顺序,WHERE 子句中查询条件的安排顺序依赖于被索引的列,同时也依赖于哪个条件检索的记录最少。
我们先了解一个概念:“最严格限定条件”。最严格限定条件是指返回一个表中最少记录数的条件。我们在 Oracle 系统中编写 SQL 语句时,最严格限定条件一般放在WHERE 子句的最后,因为 Oracle 的查询优化器是从后向前读 WHERE 子句的。先处理最严格限定条件,返回的记录最少,也就是在处理下一个条件之前得到最小的结果集,后面条件的处理花费的时间也就越少,系统的性能就到了提高。如下例(表 Employee见附录 I):
SELECT name, sex, id, salary
FROM Employee
WHERE id < 5000 AND salary > 4000
我们对上面的 SQL 语句进行分析,可以把这个过程想象为对表进行两次扫描操作的组合。在表 Employee 中,符合条件 salary > 4000 的记录列表如下:
Results
name sex id salary
———— ——— —— ————
林志千 男 1001 6000.00
李明 男 1002 5000.00
陈广海 男 2001 5000.00
张宇 男 3001 5000.00
张峰 男 4001 7000.00
魏华翔 男 4003 6000.00
王亚鹏 男 4004 6000.00
李志深 男 5001 5000.00
魏成 男 6001 5000.00
[9rows]
得到这个结果,是经过了整个表的扫描,即读取了 24 条记录。接着处理条件 id < 5000,这一次只需要在上面的结果集中进行扫描,扫描的记录数为 9 条,总共扫描记录数为 33 次。如果我们将语句的条件换个顺序:
SELECT name, sex, id, salary
FROM Employee
WHERE salary > 4000 AND id < 5000
我们再次对上面的 SQL 语句进行分析,同样,把语句的执行过程想象为对表进行两次扫描操作的组合。在表 Employee 中,符合条件 id < 5000 的记录列表如下:
Results
name sex id salary
———— —— —— ————
林志千 男 1001 6000.00
李明 男 1002 5000.00
李大平 男 1003 3000.00
林国荣 男 1004 4000.00
庞文凯 男 1005 3000.00
陈广海 男 2001 5000.00
刘燕 女 2002 3000.00
林志祥 男 2003 3000.00
张宇 男 3001 5000.00
吴忠彦 男 3002 3000.00
魏箐 女 3003 4000.00
王静 女 3004 3000.00
张峰 男 4001 7000.00
张敏燕 女 4002 4000.00
魏华翔 男 4003 6000.00
王亚鹏 男 4004 6000.00
林雪飞 女 4005 4000.00
姜艳成 女 4006 4000.00
[18rows]
这个中间结果共有 18 条记录,它的得出也是经过了整个表的扫描,即读取了 24 条记录。接着处理条件 salary > 4000,这一次扫描的记录数为 18 条,总共扫描记录数为42 次,大于第一种写法的 33 次。可见,SQL 语句组成成分的执行顺序会影响语句的性
能。上面举的只是一个小表的例子,对于一个大表,不合理的条件书写顺序可能会导致有一个中间结果的记录条数非常庞大,从而大大降低了 SQL 执行的速度。所以我们一定要注意安排这些组成部分的书写顺序,尽量安排返回结果集最小的条件先被查询优化
器处理。 以上两个 SQL 语句运行的最后结果是相同的:
Results
name sex id salary
———— ——— —— ————
林志千 男 1001 6000.00
李明 男 1002 5000.00
陈广海 男 2001 5000.00
张宇 男 3001 5000.00
张峰 男 4001 7000.00
魏华翔 男 4003 6000.00
王亚鹏 男 4004 6000.00
李志深 男 5001 5000.00
[8rows]
要保证编写的 SQL 语句的高性能,大家还要尽量避免使用逻辑操作符 OR,因为OR 运算不可避免地会降低几乎所有查询的执行效率。笔者由经验所得,使用 IN 运算来代替 OR 运算,系统的效率可以得到提高。
SELECT name, sex, id, salary
FROM Employee
WHERE SUBSTR(TO_CHAR(id),1,1) = ’1’ OR
SUBSTR(TO_CHAR(id),1,1) = ’2’ OR
SUBSTR(TO_CHAR(id),1,1) = ’3’ OR
SUBSTR(TO_CHAR(id),1,1) = ’4’
我们可以将上面的使用了大量OR运算符的SQL语句在不改变它的查询结果的条件下进行修改, 用 IN 来替换操作符 OR, 以增加语句的执行效率,提高数据库系统的性能。下面是被修改后的 SQL 语句:
SELECT name, sex, id, salary
FROM Employee
WHERE SUBSTR(TO_CHAR(id),1,1)
IN (’1’, ’2’, ’3’, ’4’)
Results
name sex id salary
———— ——— —— ————
林志千 男 1001 6000.00
李明 男 1002 5000.00
李大平 男 1003 3000.00
林国荣 男 1004 4000.00
庞文凯 男 1005 3000.00
陈广海 男 2001 5000.00
刘燕 女 2002 3000.00
林志祥 男 2003 3000.00
张宇 男 3001 5000.00
吴忠彦 男 3002 3000.00
魏箐 女 3003 4000.00
王静 女 3004 3000.00
张峰 男 4001 7000.00
张敏燕 女 4002 4000.00
魏华翔 男 4003 6000.00
王亚鹏 男 4004 6000.00
林雪飞 女 4005 4000.00
姜艳成 女 4006 4000.00
[18rows]