我们都了解索引是相关表概念部分,主要是提高检索数据的相关效率,当oracle使用了较为复杂的自平衡b-tree结构时。我们一般是通过索引查询数据比全表扫描要快。当 oracle找出执行查询和update语句的最好路径时,oracle优化将使用索引。同样在联结多个表时使用
我们都了解索引是相关表概念部分,主要是提高检索数据的相关效率,当oracle使用了较为复杂的自平衡b-tree结构时。我们一般是通过索引查询数据比全表扫描要快。当 oracle找出执行查询和update语句的最好路径时, oracle优化将使用索引。同样在联结多个表时使用索引也能够提高效率。
另一个使用索引的好处是,他提供了主键(primary key)的唯一性验证。那些long或long raw数据类型, 您能够索引几乎任何的列。通常, 在大型表中使用索引特别有效. 当然,您也会发现, 在扫描小表时,使用索引同样能提高效率。虽然使用索引能得到查询效率的提高,但是我们也必须注意到他的代价。
索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改。这意味着每条记录的insert,delete , update将为此多付出4、 5次的磁盘i/o 。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。定期的重构索引是有必要的:
alter index rebuild
1.用exists替换distinct:
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在select子句中使用distinct。一般能够考虑用exist替换, exists 使查询更为迅速,因为rdbms核心模块将在子查询的条件一旦满足后,立即返回结果。例子:
(低效): select distinct dept_no,dept_name from dept d , emp e where d.dept_no = e.dept_no (高效): select dept_no,dept_name from dept d where exists ( select ‘x' from emp e where e.dept_no = d.dept_no);
2.sql语句用大写的;因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行。
3.在java代码中尽量少用连接符“+”连接字符串。
4.避免在索引列上使用not通常,我们要避免在索引列上使用not, not会产生在和在索引列上使用函数相同的影响。当oracle“碰到”not,他就会停止使用索引转而执行全表扫描。
5.避免在索引列上使用计算。where子句中,假如索引列是函数的一部分。oracle优化器将不使用索引而使用全表扫描。
举例:
低效: select … from dept where sal * 12 > 25000; 高效: select … from dept where sal > 25000/12;
6.用>=替代>:
高效:select * from emp where deptno >=4 低效: select * from emp where deptno >3
两者的区别在于,前者dbms将直接跳到第一个dept等于4的记录而后者将首先定位到deptno=3的记录并且向前扫描到第一个dept大于3的记录。
7.用union替换or (适用于索引列):
通常情况下,用union替换where子句中的or将会起到较好的效果。对索引列使用or将造成全表扫描。注意,以上规则只针对多个索引列有效。假如有column没有被索引,查询效率可能会因为您没有选择or而降低。在下面的例子中,loc_id 和region上都建有索引。
高效:select loc_id 。 loc_desc ,region from location where loc_id = 10 union select loc_id ,loc_desc ,region from location where region = “melbourne”
低效: select loc_id ,loc_desc ,region from location where loc_id = 10 or region = “melbourne”
8.用in来替换or:
这是一条简单易记的规则,但是实际的执行效果还须检验,在oracle8i下,两者的执行路径似乎是相同的:
低效:
select…. from location where loc_id = 10 or loc_id = 20 or loc_id = 30
高效:
select… from location where loc_in in (10,20,30);
9.避免在索引列上使用is null和is not null:
避免在索引中使用任何能够为空的列,oracle将无法使用该索引。对于单列索引,假如列包含空值,索引中将不存在此记录。对于复合索引,假如每个列都为空,索引中同样不存在此记录。假如至少有一个列不为空,则记录存在于索引中。举例:假如唯一性索引建立在表的a列和b列上,并且表中存在一条记录的 a,b值为(123,null), oracle将不接受下一条具备相同a,b值(123,null)的记录(插入)。
然而假如任何的索引列都为空,oracle将认为整个键值为空而空不等于空。因此您能够插入1000 条具备相同键值的记录,当然他们都是空! 因为空值不存在于索引列中,所以where子句中对索引列进行空值比较将使oracle停用该索引。
低效: (索引失效)
select … from department where dept_code is not null;
高效:(索引有效)
select … from department where dept_code >=0;
10.总是使用索引的第一个列:
假如索引是建立在多个列上,只有在他的第一个列(leading column)被where子句引用时,oracle优化器才会选择使用该索引。这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。
11.用union-all 替换union ( 假如有可能的话):
当sql语句需要union两个查询结果集合时,这两个结果集合会以union-all的方式被合并,然后在输出最终结果前进行排序。假如用 union all替代union,这样排序就不是必要了。效率就会因此得到提高。需要注意的是,union all 将重复输出两个结果集合中相同记录。因此各位还是要从业务需求分析使用union all的可行性。 union 将对结果集合排序,这个操作会使用到sort_area_size这块内存。对于这块内存的oracle优化也是相当重要的。下面的sql能够用来查询排序的消耗量:
低效: select acct_num, balance_amt from debit_transactions where tran_date = '31-dec-95' union select acct_num, balance_amt from debit_transactions where tran_date = '31-dec-95' 高效: select acct_num, balance_amt from debit_transactions where tran_date = '31-dec-95' union all select acct_num, balance_amt from debit_transactions where tran_date = '31-dec-95'
如果你是oracle多表查询优化方面的新手,对oracle多表查询优化的相关实际应用不是很了解的话,以下的文章会给你提供更全面的知识。以下就是文章的详细内容的介绍,望你会有所了解。
oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须写在其他where条件之前, 那些可以过滤掉最大数量记录的条件必须写在where子句的末尾.
例如:
(低效,执行时间156.3秒)
select … from emp e where sal >; 50000 and job = ‘manager’ and 25 (select count(*) from emp where mgr=e.empno);
(高效,执行时间10.6秒)
select … from emp e where 25 (select count(*) from emp where mgr=e.empno) and sal >; 50000 and job = ‘manager’;
重点关注3:select子句中避免使用 ‘ * ‘ .重点关注
当你想在select子句中列出所有的column时,使用动态sql列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,oracle在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过oracle多表查询数据字典完成的, 这意味着将耗费更多的时间.
7. 减少访问数据库的次数
当执行每条sql语句时, oracle在内部执行了许多工作: 解析sql语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少oracle的工作量.
例如,
以下有三种方法可以检索出雇员号等于0342或0291的职员.
方法1 (最低效)
select emp_name , salary , grade from emp where emp_no = 342; select emp_name , salary , grade from emp where emp_no = 291;
方法2 (次低效)
declare cursor c1 (e_no number) is select emp_name,salary,grade from emp where emp_no = e_no; begin open c1(342); fetch c1 into …,..,.. ; open c1(291); fetch c1 into …,..,.. ; close c1; end;
以上的相关内容就是对oracle多表查询优化的介绍,望你能有所收获。