使用索引的误区之一:没有使用复合索引的前导列导致查询不使用索引
2024-07-21 02:11:41
供稿:网友
国内最大的酷站演示中心!
使用索引的误区之一:没有使用复合索引的前导列导致查询不使用索引
在oracle中,我们经常以为建立了索引,sql查询的时候就会如我们所希望的那样使用索引,事实上,oracle只会在一定条件下使用索引,这里我们总结数第一点:oracle会在条件中包含了前导列时使用索引,即查询条件中必须使用索引中的第一个列,请看下面的例子
sql> select * from tab;
tname tabtype clusterid
------------------------------ ------- ----------
bonus table
dept table
dummy table
emp table
salgrade table
建立一个联合索引(注意复合索引的索引列顺序)
sql> create index emp_id1 on emp(empno,ename,deptno);
index created
建立一个单键索引
sql> create index emp_id2 on emp(sal);
index created
sql> select table_name,index_name from user_indexes
2 where table_name='emp';
table_name index_name
------------------------------ ------------------------------
emp emp_id1
emp emp_id2
sql> select * from user_ind_columns
2 /
index_name table_name column_name column_position column_length char_length descend
------------------------------ ------------------------------ -------------------------------------------------------------------------------- --------------- ------------- ----------- -------
emp_id1 emp empno 1 22 0 asc
emp_id1 emp ename 2 10 10 asc
emp_id1 emp deptno 3 22 0 asc
emp_id2 emp sal 1 22 0 asc
下面的查询由于没有使用到复合索引的前导列,所以没有使用索引
select job, empno from emp where ename='rich';
plan_table_output
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
--------------------------------------------------------------------
| 0 | select statement | | | | |
|* 1 | table access full | emp | | | |
--------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
1 - filter("emp"."ename"='rich')
note: rule based optimization
14 rows selected
下面的查询也由于没有使用到复合索引的前导列,所以没有使用索引
select job, empno from emp where deptno=30;
plan_table_output
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
--------------------------------------------------------------------
| 0 | select statement | | | | |
|* 1 | table access full | emp | | | |
--------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
1 - filter("emp"."deptno"=30)
note: rule based optimization
14 rows selected
下面的查询使用了复合索引中的前导列,所以查询走索引了
select job, empno from emp where empno=7777;
plan_table_output
--------------------------------------------------------------------------------
---------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
---------------------------------------------------------------------------
| 0 | select statement | | | | |
| 1 | table access by index rowid| emp | | | |
|* 2 | index range scan | emp_id1 | | | |
---------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - access("emp"."empno"=7777)
note: rule based optimization
15 rows selected
下面的查询使用了复合索引中的第一列和第二列,所以查询走索引了
select job, empno from emp where empno=7777 and ename='rich';
plan_table_output
--------------------------------------------------------------------------------
---------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
---------------------------------------------------------------------------
| 0 | select statement | | | | |
| 1 | table access by index rowid| emp | | | |
|* 2 | index range scan | emp_id1 | | | |
---------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - access("emp"."empno"=7777 and "emp"."ename"='rich')
note: rule based optimization
15 rows selected
使用了复合索引的全部列,所以走索引了,另外由于选了了索引中没有包含的列(job),
所以进行索引全表扫描得到满足条件的rowid后,还要到表中检索相应的行
select job, empno from emp where empno=7777 and ename='rich' and deptno=30;
plan_table_output
--------------------------------------------------------------------------------
---------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
---------------------------------------------------------------------------
| 0 | select statement | | | | |
| 1 | table access by index rowid| emp | | | |
|* 2 | index range scan | emp_id1 | | | |
---------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - access("emp"."empno"=7777 and "emp"."ename"='rich' and "emp"."dep
tno"=30)
note: rule based optimization
16 rows selected
使用了复合索引的全部列,所以走索引了,而且由于所有选择的列都包含在索引中,所以仅仅进行了索引范围扫描
select empno from emp where empno=7777 and ename='rich' and deptno=30;
plan_table_output
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
--------------------------------------------------------------------
| 0 | select statement | | | | |
|* 1 | index range scan | emp_id1 | | | |
--------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
1 - access("emp"."empno"=7777 and "emp"."ename"='rich' and "em
p"."deptno"=30)
note: rule based optimization
15 rows selected