本章提要
--------------------------------------
数据库引擎如何访问数据
定位表中数据:
1) 扫描全表
2) 基于荣誉访问结构(比如 索引)进行查找, 或基于表本身的结构(比如, 哈希聚簇)进行查找
--------------------------------------
9.1 照出不理想的访问路径
一般的, 一个访问路径所使用的资源和返回的行的总数成比例的话是可以接受的, 也就是说, 返回的行少, 消耗的资源就少, 返回的行多,
消耗的资源就多, 并不是越快越好, 主要还是要看一个性价比, 消耗资源和速度的性价比.
消耗资源包括, cpu, 内存, 磁盘, 网络.
逻辑读非常接近总的资源开销, 一般可以考虑如下"经验法则":
~ 每个返回行少于5个逻辑读的访问路径可能是不错的.
~ 每个返回行10~15个逻辑读的访问路径是可以接受的.
~ 每个返回行多于15~20个逻辑读可能是低效的. 换句话说, 可能存在调优的余地.
低效的原因:
~ 没有提供合适的访问结构(比如, 索引)
~ 提供了合适的访问结构, 不过SQL语句的语法并不允许查询优化器使用它.
~ 表或者索引是分区的, 不过不可能进行修剪(pruning), 因此, 要访问所有的分区.
~ 表或索引, 或者两者, 都没有分区.
~ 查询优化器因缺少统计信息而造成错误评估
9.2 具有弱选择性的SQL语句
全表扫描
在全表扫描过程中, 数据库引擎顺次读取表在高水位下的所有数据块, 所以, 逻辑读的数量依赖于块的数量而不是行数. 全表扫描可能
是不够理想的, 尤其在表包含大量空的或者接近空的块时, 很明显, 一个块必须先读才能知道它是否包含数据. 当表删除操作比插入
操作多的时候, 最容易导致表包含许多稀疏的数据块.
要降低高水位, 有必须对表进行重组, 注意行迁移必须激活, 因为重组过程中有的rowid产生
alter table t enable row movement;
alter table t shrink space;
9.3 具有枪选择性的SQL语句
要高效处理强选择性的SQL语句, 数据应该通过rowid, 索引或单表哈希聚簇来访问.
使用 rowid 不用说, 单行查询, 但是首先你要先知道rowid的值, 再用类似 select * from t where rowid = 'ABAAFAABAAA';
使用索引:
create table t ( id number, pad varchar2(4000), constraint t_pk primary key(id) ); insert into t select rownum as id, dbms_random.string('p', 500) as pad from dual connect by level <= 1000; select blocks, num_rows from user_tables where table_name = 'T'; /* result BLOCKS NUM_ROWS ---------- ---------- 73 1000 */ SELECT blevel, leaf_blocks, clustering_factor FROM user_indexes WHERE index_name = 'T_PK'; /* result BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR ---------- ----------- ----------------- 1 2 72 */
因为索引中并不存储null的值,所以如果条件包含 is null, 那么查询优化器可能不利用索引