表扫描与索引扫描
• 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
• 注意了,是不是与无排序条件的相反
• 因为,如果把rownum与order 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.