ORACLE SQL性能优化系列 5

25. 用索引提高效率
索引是表的一个概念部分 , 用来提高检索数据的效率 . 实际上 ,ORACLE 使用了一个复杂的自平衡 B-tree 结构 . 通常 , 通过索引查询数据比全表扫描要快 . ORACLE 找出执行查询和 Update 语句的最佳路径时 , ORACLE 优化器将使用索引 . 同样在联结多个表时使用索引也可以提高效率 . 另一个使用索引的好处是 , 它提供了主键 (primary key) 的唯一性验证 .

除了那些 LONG LONG RAW 数据类型 , 你可以索引几乎所有的列 . 通常 , 在大型表中使用索引特别有效 . 当然 , 你也会发现 , 在扫描小表时 , 使用索引同样能提高效率 .

虽然使用索引能得到查询效率的提高 , 但是我们也必须注意到它的代价 . 索引需要空间来

存储 , 也需要定期维护 , 每当有记录在表中增减或索引列被修改时 , 索引本身也会被修改 . 这意味着每条记录的 INSERT , DELETE , UPDATE 将为此多付出 4 , 5 次的磁盘 I/O . 因为索引需要额外的存储空间和处理 , 那些不必要的索引反而会使查询反应时间变慢 .

译者按:
定期的重构索引是有必要的 .

ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>


26.
索引的操作
ORACLE
对索引有两种访问模式 .

索引唯一扫描 ( INDEX UNIQUE SCAN)
大多数情况下 , 优化器通过 WHERE 子句访问 INDEX.
例如:

LODGING 有两个索引 : 建立在 LODGING 列上的唯一性索引 LODGING_PK 和建立在 MANAGER 列上的非唯一性索引 LODGING$MANAGER.

SELECT *
FROM LODGING
WHERE LODGING = ‘ROSE HILL';

在内部 , 上述 SQL 将被分成两步执行 , 首先 , LODGING_PK 索引将通过索引唯一扫描的方式被访问 , 获得相对应的 ROWID, 通过 ROWID 访问表的方式 执行下一步检索 .

如果被检索返回的列包括在 INDEX 列中 ,ORACLE 将不执行第二步的处理 ( 通过 ROWID 访问表 ). 因为检索数据保存在索引中 , 单单访问索引就可以完全满足查询结果 .

下面 SQL 只需要 INDEX UNIQUE SCAN 操作 .

SELECT LODGING
FROM LODGING
WHERE LODGING = ‘ROSE HILL';

索引范围查询(INDEX RANGE SCAN)

适用于两种情况 :
      1.
基于一个范围的检索
      2.
基于非唯一性索引的检索

1:

SELECT LODGING
FROM LODGING
WHERE LODGING LIKE ‘M%';

WHERE
子句条件包括一系列值 , ORACLE 将通过索引范围查询的方式查询 LODGING_PK . 由于索引范围查询将返回一组值 , 它的效率就要比索引唯一扫描低一些 .
2:

SELECT LODGING
FROM LODGING
WHERE MANAGER = ‘BILL GATES';

这个 SQL 的执行分两步 , LODGING$MANAGER 的索引范围查询 ( 得到所有符合条件记录的 ROWID) 和下一步同过 ROWID 访问表得到 LODGING 列的值 . 由于 LODGING$MANAGER 是一个非唯一性的索引 , 数据库不能对它执行索引唯一扫描 .

由于 SQL 返回 LODGING , 而它并不存在于 LODGING$MANAGER 索引中 , 所以在索引范围查询后会执行一个通过 ROWID 访问表的操作 .

WHERE
子句中 , 如果索引列所对应的值的第一个字符由通配符 (WILDCARD) 开始 , 索引将不被采用 .

SELECT LODGING
FROM LODGING
WHERE MANAGER LIKE
‘% HANMAN';

在这种情况下, ORACLE 将使用全表扫描 .


 27.
基础表的选择
基础表 (Driving Table) 是指被最先访问的表 ( 通常以全表扫描的方式被访问 ). 根据优化器的不同 , SQL 语句中基础表的选择是不一样的 .

如果你使用的是 CBO (COST BASED OPTIMIZER), 优化器会检查 SQL 语句中的每个表的物理大小 , 索引的状态 , 然后选用花费最低的执行路径 .

如果你 RBO (RULE BASED OPTIMIZER) , 并且所有的连接条件都有索引对应 , 在这种情况下 , 基础表就是 FROM 子句中列在最后的那个表 .
举例:

SELECT A.NAME , B.MANAGER
FROM
  WORKER A,
LODGING B
WHERE
  A.LODGING = B.LODING;
由于 LODGING 表的 LODING 列上有一个索引 , 而且 WORKER 表中没有相比较的索引 , WORKER 表将被作为查询中的基础表 .


28.
多个平等的索引
SQL 语句的执行路径可以使用分布在多个表上的多个索引时 , ORACLE 会同时使用多个索引并在运行时对它们的记录进行合并 , 检索出仅对全部索引有效的记录 .

ORACLE 选择执行路径时 , 唯一性索引的等级高于非唯一性索引 . 然而这个规则只有

WHERE 子句中索引列和常量比较才有效 . 如果索引列和其他表的索引类相比较 . 这种子句在优化器中的等级是非常低的 .

如果不同表中两个想同等级的索引将被引用 , FROM 子句中表的顺序将决定哪个会被率先使用 . FROM 子句中最后的表的索引将有最高的优先级 .

如果相同表中两个想同等级的索引将被引用 , WHERE 子句中最先被引用的索引将有最高的优先级 .
举例:

DEPTNO
上有一个非唯一性索引 ,EMP_CAT 也有一个非唯一性索引 .

SELECT ENAME,
FROM EMP
WHERE DEPT_NO = 20
AND EMP_CAT = ‘A';

这里 ,DEPTNO 索引将被最先检索 , 然后同 EMP_CAT 索引检索出的记录进行合并 . 执行路径如下 :

TABLE ACCESS BY ROWID ON EMP
AND-EQUAL
INDEX RANGE SCAN ON DEPT_IDX
INDEX RANGE SCAN ON CAT_IDX

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值