WEB分页与优化技术

Posted by Vincent on September 8, 2008

表扫描与索引扫描

•    Where a=41

•    表扫描(假定没有索引)

– 1、扫描所有的该表的数据块

– 2、从数据块中找到记录,并过滤

– 需要扫描该表所有的数据块

•    索引扫描

– 1、在索引中搜索a=41的位置(一般只扫描3个块左右R->B->L

– 2、获得所有a=41的相关行的rowid

– 3、根据rowid,回表查询数据,如果数据量少,回表就少

– 假定需要的数据都在索引中,可以不回表

•    如索引为(a,b),查询为select b from table where a=41

 

•    处决于扫描的数据量对应表的总量的百分比

•    少量数据扫描,索引扫描总是好的

•    OLTP系统,尽量采用索引扫描(因为查询结果一般很小)

•    如果有可能,只在索引上查询,不用回表,或者少回表

– 回表会读取更多的块(因为表数据是无序的)

– 排序,先分页再回表(减少回表)

– 求总数,如count(*),尽量不回表

– 但是查询字段很少的查询,可以建立复合索引,避免回表

分页技术与数据库查询分页

•    搜索技术的发展,如google,已经不是普通的数据库分页技术

•    我们的讨论的分页技术都是指数据库获取数据并分页,并简称为WEB分页技术

•    我们的数据库统一为Oracle数据库,分页技术主要是rownum与分析函数

– ROWNUM,伪列,实际不存在(与rowid是不一样的)

分页案例一:无排序分页

•    无顺序要求

•    正确写法

– Select * from (select rownum rn,t.* from table t where 条件 and rownum <=n) where rn >=m

•    错误写法

– Select * from (Select rownum rn,* from (select * from table t where 条件) where rownum <=n) where rn >=m

•    特征

– 越靠前越快(正好是大部分人只对前面数据感兴趣)

– 如果有where条件,也仅仅是选出足够的数据就停止扫描,不用扫描所有块

 

分页案例二:排序分页

•    要求排序后分页(我们的大部分分页需求)

•    正确写法

– Select * from (Select rownum rn,* from (select * from table t where 条件 order by field) where rownum <=n) where rn >=m

•    错误写法

– Select * from (select rownum rn,t.* from table t where 条件 and rownum <=n order by field) where rn >=m

•    注意了,是不是与无排序条件的相反

•    因为,如果把rownumorder by写一起,是取出rownum范围内的再排序(也就是说rownum的优先级高)

•    必须要先排序

•    如果是全表扫描,必须扫描所有块

•    如果是索引扫描,必须选择出所有的数据

•    可以采用分析函数

– Select * from (select row_number over(order by field) rn,t.* from table) where rn>=m and rn <=n

 

分页优化

•    如果是很大的表,需要足够多的where条件,筛选出定量的记录并分页

•    如果有排序要求,先排序后分页

•    尽量走索引,少回表,如果实在有需要回表,先在索引上分页,再回表

– 因为索引是有序的,访问的块比较少

– 只访问索引,可以获得行的rowid,根据rowid可最终获得数据

– 如果先分页再回表,可以只回表该页的数据,不用回表所有数据


This work is licensed under a CC A-S 4.0 International License.