前言数据库
关于对Oracle数据库查询性能优化的一个简要的总结。 历来数据库优化都是一项艰巨的任务。对于大数据量,访问频繁的系统,优化工做显得尤其重要。因为Oracle系统的灵活性、复杂性、性能问题的缘由多样性以及Oralce数据库的动态特性,优化成为Oracle数据库管理中最困难的领域。做为一个对数据库了解很少的程序猿,我也只能从最基本的开始着手,慢慢来学习掌握Oracle的基础吧。性能优化
示例性能
一、避免使用select *学习
当你想在select字句中列出全部的column时,使用“select *”是一个方便的方法。不幸的是,这是一个低效的方法。实际上,Oracle在解析的过程当中,会将‘*’依次转换成全部的列名,这个工做是经过查询数据字典完成的,这意味着将耗费更多的时间。大数据
---糟糕的查询 select * from Table_Name1
---较好的查询 select columnname1,columnname2,columnname3 from Table_Name1
二、使用表的别名
当在SQL语句中链接多个表时,请使用表的别名并把别名前缀于每一个column上。这样一来,就能够减小解析的时间并减小那些由column歧义引发的语法错误。
column歧义指的是因为SQL中不一样的表具备相同的column名,当SQL语句中出现这个column时,SQL解析器没法判断这个column的归属。优化
---糟糕的查询 select columnname from Table_Name1 t1,Table_Name2
---较好的查询 select t1.columnname from Table_Name1 t1,Table_Name2
三、用Exists 替代 in
在许多基于基础表的查询中,为了知足一个条件,每每须要对另外一个表进行联接。在这种状况下,使用exists(或not exists)一般将提升查询的效率。spa
例子:从小卖部买东西(商品),假若有个库存表Table1,买东西出库表Table2.查找库存中的商品,是否有被卖出的,有的话就输出库存信息。code
--糟糕的查询
SELECT column_name
FROM table_name1
WHERE column_name IN
( SELECT column_name
FROM table_name2)
---较好的查询 SELECT column_name FROM table_name1 outer WHERE EXISTS (SELECT 1 FROM table_name2 inner WHERE inner.column_name = outer.column_name)
四、用not exists 替代 not in
在子查询中,not in子句将执行一个内部的排序和合并。不管在那种状况下,not in 都是低效的(由于它对子查询中的表执行了一个全表遍历)。为了不使用 not in ,咱们能够把它改写成外链接(outer join)或 not exists。blog
---糟糕的查询 select columnname,columnname1 from Table_Name1 where id not in(select id from Table_Name2 where name='A')
---较好的查询 select columnname,columnname1 from Table_Name1 t1,Table_Name2 t2 where t1.id=t2.id and t2.name<>'A'
---更好的查询 select columnname,columnname1 from Table_Name1 t1 where not exists(select 1 from Table_Name2 t2 where t2.id=t1.id and t2.name='A')
五、用表链接替换Exists
一般来讲,采用表链接的方式比Exists更有效率。
可是不少状况下咱们没法将Exists改编为链接。排序
---糟糕的查询 select columnname,columnname1 from Table_Name1 t1 where not exists(select 1 from Table_Name2 t2 where t2.id=t1.id and t2.name='A')
---较好的查询 select columnname,columnname1 from Table_Name1 t1 join Table_Name2 t2 on t1.id=t2.id where t2.name='A'
六、用exists替换distinct
当提交一个包含一对多表信息(好比部门表和雇员表)的查询时,避免在select字句中使用distinct。通常能够考虑用Exists替换。Exists使查询更为迅速,由于RDBMS核心模块将在子查询的条件一旦知足后,马上返回结果。
例子:从小卖部买东西(商品),假若有个库存表Table_Name1,买东西出库表Table_Name2.查找库存中的商品,是否有被卖出的,有的话就输出库存信息。
--糟糕的查询
SELECT DISTINCT t1.column_name
FROM table_name1 t1, table_name2 t2
WHERE t1.column_name = t2.column_name;
---较好的查询 SELECT column_name FROM table_name1 outer WHERE EXISTS (SELECT 1 FROM table_name2 inner WHERE inner.column_name = outer.column_name)
七、用>=替换>
若是id上有一个索引,则:
///糟糕的查询 select * from EMP where id>3;
//较好的查询 select * from EMP where id>=4;
二者的区别在于,后者将直接跳转到第一个id等于4的记录而前者将首先定位到id=3的记录而且向前扫描到第一个id大于3的记录。
八、用UNION替换OR
一般状况下,用UNION替换where字句中的OR将会起到较好的效果。对索引列使用OR将形成全表扫描。注意,以上规则只针对多个索引列有效。查询效率可能会由于没有选择OR而下降。
---糟糕的查询 select id,name,reg where Table_Name1 where id=10 or reg='A'
---较好的查询 select id,name,reg from Table_Name1 t1 where t1.id=10 union select id,name,reg from Table_Name2 t2 where t2.reg='A'
固然以上要基于id列和reg列都是索引列。
九、用UNION-ALL 替换UNION
当SQL语句须要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并,而后在输出最终结果前进行排序,并将重复记录过滤掉。
若是用UNION ALL替代UNION,这样排序就不是必要了,效率会所以获得提升。
须要注意的是,UNION ALL将重复输出两个结果集合中相同记录,所以仍是要从业务需求 分析使用UNION ALL的可行性。
---糟糕的查询,须要进行排序 select id,name,reg from Table_Name1 t1 where t1.id=10 union select id,name,reg from Table_Name2 t2 where t2.id=10
---较好的查询,不须要排序 select id,name,reg from Table_Name1 t1 where t1.id=10 union all select id,name,reg from Table_Name2 t2 where t2.id=10
考虑的时候必定也要基于业务的需求进行取舍。
十、避免在索引列上使用IS NULL和IS NOT NULL
对于单列索引,若是列包含空值,索引中将不存在此记录。
对于复合索引,若是每一个列都为空,索引中一样不存在此记录。若是至少有一个列不为空。则记录存在于索引中。
由于空值不存在于索引列中,因此where子句中对索引列进行空值比较将使Oracle停用该索引。
---糟糕的查询 select id,name,reg from Table_Name1 t1 where t1.id is not null
---较好的查询 select id,name,reg from Table_Name2 t2 where t2.id>=10
前提仍是id列是索引列
总结
本节暂时总结到这里,以后继续进行总结,感受仍是颇有用的,而后在平常的工做中加以实践,应该对本身的能力有所改善。上面总结的都是常规的作法,固然具体优化还要根据具体的环境进行处理,处理方式复杂多变,但万变不离其宗。若有错误,请及时通知加以更正,谢谢。