** 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
** 29. ** ** ** ** 等式比较和范围比较 **
当 WHERE 子句中有索引列 ** , ** ORACLE 不能合并它们 ,ORACLE 将用范围比较 .
举例 :
DEPTNO 上有一个非唯一性索引 ,EMP_CAT 也有一个非唯一性索引 .
SELECT ENAME
FROM EMP
WHERE DEPTNO > 20
AND EMP_CAT = ‘A’;
这里只有 EMP_CAT 索引被用到 , 然后所有的记录将逐条与 DEPTNO 条件进行比较 . 执行路径如下 :
TABLE ACCESS BY ROWID ON EMP
INDEX RANGE SCAN ON CAT_IDX
** 30. ** ** 不明确的索引等级 **
当 ORACLE 无法判断索引的等级高低差别 , 优化器将只使用一个索引 , 它就是在 WHERE 子句中被列在最前面的 .
举例 :
DEPTNO 上有一个非唯一性索引 ,EMP_CAT 也有一个非唯一性索引 .
SELECT ENAME
FROM EMP
WHERE DEPTNO > 20
AND EMP_CAT > ‘A’;
这里 , ORACLE 只用到了 DEPT_NO 索引 . 执行路径如下 :
TABLE ACCESS BY ROWID ON EMP
INDEX RANGE SCAN ON DEPT_IDX
** 译者按 : **
** 我们来试一下以下这种情况 : **
** SQL> select index_name, uniqueness from user_indexes where table_name = 'EMP'; **
** INDEX_NAME UNIQUENES **
** ------------------------------ --------- **
** EMPNO UNIQUE **
** EMPTYPE NONUNIQUE **
** SQL> select * from emp where empno >= 2 and emp_type = 'A' ; **
** no rows selected **
** Execution Plan **
** ---------------------------------------------------------- **
** 0 SELECT STATEMENT Optimizer=CHOOSE **
** 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' **
** 2 1 INDEX (RANGE SCAN) OF 'EMPTYPE' (NON-UNIQUE) **
** 虽然 EMPNO ** ** 是唯一性索引 , ** ** 但是由于它所做的是范围比较 , ** ** 等级要比非唯一性索引的等式比较低 ! **