Where子句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句
根据这个原理表之间的连接必须写在其他WHERE条件之前 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾
举例
(低效)select … from table t where tsal > and tjobtype = and < (select count(*) from table t where tpno = ttno;(高效)select … from table t where < (select count(*) from table t where tpno = ttno and tsal > and tjobtype = ;Select子句中避免使用 *
当你想在select子句中列出所有的column时使用动态SQL列引用 * 是一个方便的方法
不幸的是这是一个非常低效的方法
实际上ORACLE在解析的过程中会将 * 依次转换成所有的列名 这个工作是通过查询数据字典完成的 这意味着将耗费更多的时间
减少访问数据库的次数
当执行每条SQL语句时ORACLE在内部执行了许多工作
解析SQL语句估算索引的利用率绑定变量读数据块等等
由此可见减少访问数据库的次数就能实际上减少ORACLE的工作量
举例
题目——我要查找编号为学生的信息
(低效)select nameagegenderaddress from t_student where id = ;select nameagegenderaddress from t_student where id = ;(高效)select anameaageagenderaaddressbnamebagebgenderbaddress from t_student at_student b where aid = and bid = ;使用Decode函数来减少处理时间
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表
举例
(低效)select count(*) sum(banace) from table where dept_id = and name like anger%;select count(*) sum(banace) from table where dept_id = and name like anger%;(高效)select count(decode(dept_idXYZnull)) count_count(decode(dept_idXYZnull)) count_sum(decode(dept_iddept_idnull)) sum_sum(decode(dept_iddept_idnull)) sum_from tablewhere name like anger%;整合简单无关联的数据库访问
如果你有几个简单的数据库查询语句你可以把它们整合到一个查询中(即使它们之间没有关系)举例
(低效)select name from table where id = ;select name from table where id = ;select name from table where id = ;(高效)select tname tname tnamefrom table t table t table twhere tid(+) = and tid(+) = and tid(+) =
【注上面例子虽然高效但是可读性差需要量情而定啊!】[nextpage]
删除重复记录
最高效的删除重复记录方法 ( 因为使用了ROWID)举例
delete from table twhere trowid > (select min(trowid) from table t where tid = tid)尽量不要使用having子句可以考虑用where替换
having只会在检索出所有记录之后才对结果集进行过滤 这个处理需要排序总计等操作
如果能通过where子句限制记录的数目那就能减少这方面的开销[nextpage]
尽量用表的别名
当在SQL语句中连接多个表时请使用表的别名并把别名前缀于每个Column上
这样一来就可以减少解析的时间并减少那些由Column歧义引起的语法错误
用exists替代in(发现好多程序员不知道这个怎么用)
在许多基于基础表的查询中为了满足一个条件往往需要对另一个表进行联接
在这种情况下使用exists(或not exists)通常将提高查询的效率
举例
(低效)select … from table t where tid > and pno in (select no from table where name like www%)(高效)select … from table t where tid > and exists (select from table t where tpno = tno and name like www%)用not exists替代not in
在子查询中not in子句将执行一个内部的排序和合并
无论在哪种情况下not in都是最低效的 (因为它对子查询中的表执行了一个全表遍历)
为了避免使用not in我们可以把它改写成外连接(Outer Joins)或not exists
用exists替换distinct
当提交一个包含一对多表信息的查询时避免在select子句中使用distinct 一般可以考虑用exists替换举例
(低效)select distinct ddept_no ddept_name from t_dept d t_emp e where ddept_no = edept_no;(高效)select ddept_no ddept_name from t_dept d where exists (select from t_emp where ddept_no = edept_no)exists使查询更为迅速因为RDBMS核心模块将在子查询的条件一旦满足后立刻返回结果
用表连接替换exists
通常来说采用表连接的方式比exists更有效率
举例
(低效)select ename from emp e where exists (select from dept where dept_no = edept_no and dept_cat = W)SELECT ENAME(高效)select ename from dept d emp e where edept_no = ddept_no and dept_cat = W;避免在索引列上使用is null和is not null避免在索引中使用任何可以为空的列ORACLE将无法使用该索引
对于单列索引如果列包含空值索引中将不存在此记录对于复合索引如果每个列都为空索引中同样不存在此记录如果至少有一个列不为空则记录存在于索引中
举例
如果唯一性索引建立在表的A列和B列上 并且表中存在一条记录的AB值为(null)ORACLE将不接受下一条具有相同AB值(null)的记录(插入)然而如果所有的索引列都为空ORACLE将认为整个键值为空而空不等于空
因此你可以插入 条具有相同键值的记录当然它们都是空!
因为空值不存在于索引列中所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引