>  기사  >  데이터 베이스  >  ORACLE回表

ORACLE回表

WBOY
WBOY원래의
2016-06-07 15:37:511875검색

要写出高效的SQL,那么必须必须得清楚SQL执行路径,介绍如何提高SQL性能的文章很多,这里不再赘述,本人来谈谈如何从 减少SQL回表次数 来提高查询性能,因为回表将导致扫描更多的数据块。 我们大家都知道,数据库表中数据存储都是以块为单位,称为数据块;表

要写出高效的SQL,那么必须必须得清楚SQL执行路径,介绍如何提高SQL性能的文章很多,这里不再赘述,本人来谈谈如何从 减少SQL回表次数 来提高查询性能,因为回表将导致扫描更多的数据块。

   我们大家都知道,数据库表中数据存储都是以块为单位,称为数据块;表中每行数据都有唯一的地址标志ROWID。

  举个例子:

    select a from test_db where b=5

   A、假设b上没有索引

         1、那么该条SQL将进行表扫描,扫描所有该表的数据块

         2、从数据块中找到记录,并且进行过滤

      可想而知,没有索引将会导致扫描该表所有数据块,性能低下

  B、 假设b上有索引

        1、那么该条SQL将进行索引扫描,在索引中找到b=5的位置,一般只需要扫描3个块左右就找到了

        2、获得所有b=5的行的rowid

        3、根据rowid再查询数据(这就是回表),如果数据量少,那么回表次数就少,如果需要的数据全部在索引中,那么就不会再回表了,例如a也在索引中,如果a不在索引中,那么仍然要回表一次查出a。

        经验:如果有可能的话,尽量只在索引上查询,不用回表或者只少量回表。

         例如分页需要回表,一般尽量在索引上分页,然后返回rowid,再通过rowid进行回表查询。

    下面是一个常用的分页语句:

   Select * from (select row_number over(order by a) rn,t.* from table t where b=? And c=?) where rn>=1 and rn Select * from (select row_number over(order by a) rn,t.* from table t where b=? And c=?) where rn>=1 and rn

 我们分析一下(假设索引是b,c,a):

   1、先查询内层语句 select * from table t where b=? and c=?,假设返回1000行数据

   2、通过索引找到这1000行数据的rowid,因为索引是连续的,假设这1000行数据的索引分布在5个块中,则差不多为8块读

   3、再根据rowid取回表查询数据,最坏的情况是这1000行数据分布在1000个块中,则需要读取1000块。那么算上上面的8块总共尧都区1000+8=1008块

我们换一种写法:

 Select * from table t,   
(select rid from (select rowid rid,row_number over(order by a) rn from table where b=? And c=?)   
 where rn>=1 and rn Where tmp.rid=t.rowid   
Select * from table t,
(select rid from (select rowid rid,row_number over(order by a) rn from table where b=? And c=?)
 where rn>=1 and rn Where tmp.rid=t.rowid

再来分析一下:

  1、最里层的sql select rid from (select rowid rid,row_number over(order by a) rn from table where b=? And c=?) where rn>=1 and rn

 2、分页之后,只有20行数据,再根据这20行的rowid回表查询数据,最坏情况是20行都在20个不同块中,那么总共20+8=28

     从以上分析可以看出,有效的利用索引,减少回表次数,可以大大提高SQL性能,值得大家去花功夫了解一下。


http://blog.csdn.net/lovingprince/archive/2009/04/16/4084786.aspx

http://blog.csdn.net/gybyylx/archive/2010/12/11/6070340.aspx

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.