在我们的Oracle安装的表中,我们有一个表,其中包含两个列(X和Y)的索引.如果我使用where子句仅对表X进行查询,那么Oracle是否能够使用索引?
例如:
表Y:Col_A,Col_B,Col_C,
索引存在于(Col_A,Col_B)
SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW';
Run Code Online (Sandbox Code Playgroud)
是否会使用索引,还是会进行表扫描?
这取决于.
您可以通过让Oracle解释执行计划来检查它:
EXPLAIN PLAN FOR
SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW';
Run Code Online (Sandbox Code Playgroud)
然后
select * from table(dbms_xplan.display);
Run Code Online (Sandbox Code Playgroud)
所以,举例来说
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);
Run Code Online (Sandbox Code Playgroud)
然后一个
explain plan for
select * from table_y
where col_a = 'STACKOVERFLOW';
select * from table(dbms_xplan.display);
Run Code Online (Sandbox Code Playgroud)
计划(在我的安装上)看起来像:
------------------------------------------------------------------------------------------
| 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')
Run Code Online (Sandbox Code Playgroud)
ID 2向您显示该索引TABLE_Y_IX确实用于index range scan.
如果在另一个安装上,Oracle选择使用索引依赖很多东西.这是Oracle的查询优化器做出这个决定.
更新如果你觉得自己变得更好(性能明智,那就是)如果Oracle使用了索引,你可能想尝试一下+ index_asc(...)(参见 索引提示)
所以在你的情况下会是这样的
SELECT /*+ index_asc(TABLE_Y TABLE_Y_IX) */ *
FROM Table_Y
WHERE Col_A = 'STACKOVERFLOW';
Run Code Online (Sandbox Code Playgroud)
另外,我会确保您收集了表及其列的统计信息.您可以使用a检查上次收集统计信息的日期
select last_analyzed from dba_tables where table_name = 'TABLE_Y';
Run Code Online (Sandbox Code Playgroud)
和
select column_name, last_analyzed from dba_tab_columns where table_name = 'TABLE_Y';
Run Code Online (Sandbox Code Playgroud)
如果没有统计数据或者它们是陈旧的,请熟悉该dbms_stats程序包以收集此类统计信息.
这些统计信息是查询优化器严重依赖的数据来做出决策.
| 归档时间: |
|
| 查看次数: |
4685 次 |
| 最近记录: |