具有多列查询单列的 Oracle 索引

Posted

技术标签:

【中文标题】具有多列查询单列的 Oracle 索引【英文标题】:Oracle Index with multiple Columns querying on single column 【发布时间】:2012-08-15 14:33:27 【问题描述】:

在我们安装的 Oracle 中的一个表中,我们有一个在其中两列(X 和 Y)上有索引的表。如果我用 where 子句只触及 X 列对表进行查询,Oracle 是否能够使用索引?

例如:

表 Y: 可乐, Col_B, Col_C,

索引存在于 (Col_A, Col_B)

SELECT * FROM Table_Y WHERE Col_A = '***';

会使用索引,还是会进行表扫描?

【问题讨论】:

【参考方案1】:

视情况而定。

您可以通过让 Oracle 解释执行计划来检查它:

EXPLAIN PLAN FOR 
   SELECT * FROM Table_Y WHERE Col_A = '***';

然后

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 = '***';

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"='***')

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 = '***';

此外,我会确保您已收集有关表及其列的统计信息。您可以使用

检查上次收集统计数据的日期
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 包以收集此类统计信息。

这些统计数据是查询优化器在做出决策时非常依赖的数据。

【讨论】:

完美,帮助很大。顺便说一句,我的安装报告了表扫描,但至少我现在有能力检查。 只是想知道。执行计划的选择不取决于您是选择索引中的第一列还是第二列。也就是说,如果您选择第一列,您将获得索引范围扫描,但如果您选择第二列,您将获得全表扫描? @Gisli:Oracle 可能会选择在您的场景中使用index skip scan 的索引。 @RenéNyffenegger,大溪地和索引提示的链接已损坏。你能更新一下吗? @ajmalmhd04 我已经更新了第二个断开的链接。我无法找到旧链接的新目的地,所以我删除了它。具有讽刺意味的是,销售主键概念的供应商无法保持其网址不变。

以上是关于具有多列查询单列的 Oracle 索引的主要内容,如果未能解决你的问题,请参考以下文章

mysql单列索引多列索引的使用

MySQL处理重复键错误插入具有多个唯一索引的表;不是多列唯一索引

认识SQLServer索引以及单列索引和多列索引的不同

MySql的索引操作

多列索引 单列索引

pandas把dataframe的数据列转化为索引列实战:单列转化为索引多列转化为复合索引