在我们的Oracle安装的表中,我们有一个表,其中包含两个列(X和Y)的索引。如果我使用where子句只对表X进行查询,那么Oracle是否能够使用索引?
例如:
表Y: 可乐, Col_B, Col_C,
索引存在于(Col_A,Col_B)
SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW';
是否会使用索引,还是会进行表扫描?
答案 0 :(得分:9)
取决于。
您可以通过让Oracle解释执行计划来检查它:
EXPLAIN PLAN FOR
SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW';
然后
select * from table(dbms_xplan.display);
所以,例如
create table table_y (
col_a varchar2(30),
col_b varchar2(30),
col_c varchar2(30)
);
create unique index table_y_ix on table_y (col_a, col_b);
然后是
explain plan for
select * from table_y
where col_a = 'STACKOVERFLOW';
select * from table(dbms_xplan.display);
计划(在我的安装上)看起来像:
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 51 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TABLE_Y | 1 | 51 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TABLE_Y_IX | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL_A"='STACKOVERFLOW')
ID 2告诉您,索引TABLE_Y_IX
确实用于index range scan
。
如果在另一个安装上,Oracle选择使用索引依赖很多东西。做出此决定的是Oracle的查询优化器。
更新如果您觉得自己变得更好(表现更好),如果Oracle使用了索引,您可能需要尝试+ index_asc(...)
(请参阅index hint })
所以在你的情况下就像是
SELECT /*+ index_asc(TABLE_Y TABLE_Y_IX) */ *
FROM Table_Y
WHERE Col_A = 'STACKOVERFLOW';
此外,我会确保您已收集有关表及其列的统计信息。您可以使用
检查上次收集统计信息的日期select last_analyzed from dba_tables where table_name = 'TABLE_Y';
和
select column_name, last_analyzed from dba_tab_columns where table_name = 'TABLE_Y';
如果没有统计数据或者它们是陈旧的,请熟悉dbms_stats
包以收集此类统计信息。
这些统计信息是查询优化器严重依赖的数据来做出决策。