【发布时间】:2011-11-24 06:20:18
【问题描述】:
我的问题是关于 Oracle 11g 和 SQL 查询中索引的使用。
在我的数据库中,有一个结构如下的表:
Table tab (
rowid NUMBER(11),
unique_id_string VARCHAR2(2000),
year NUMBER(4),
dynamic_col_1 NUMBER(11),
dynamic_col_1_text NVARCHAR2(2000)
) TABLESPACE tabspace_data;
我创建了两个索引:
CREATE INDEX Index_dyn_col1 ON tab (dynamic_col_1, dynamic_col_1_text) TABLESPACE tabspace_index;
CREATE INDEX Index_unique_id_year ON tab (unique_id_string, year) TABLESPACE tabspace_index;
该表包含大约 1 到 2 百万条记录。我通过执行以下 SQL 命令从中提取数据:
SELECT distinct
"sub_select"."dynamic_col_1" "AS_dynamic_col_1","sub_select"."dynamic_col_1_text" "AS_dynamic_col_1_text"
FROM
(
SELECT "tab".* FROM "tab"
where "tab".year = 2011
) "sub_select"
不幸的是,尽管我创建了上述两个索引,但查询需要大约 1 小时才能执行。 解释计划显示 Oracle 使用“表完全访问”,即全表扫描。为什么不使用索引?
作为一个实验,我测试了以下 SQL 命令:
SELECT DISTINCT
"dynamic_col_1" "AS_dynamic_col_1", "dynamic_col_1_text" "AS_dynamic_col_1_text"
FROM "tab"
即使在这种情况下,也不会使用索引,而是执行全表扫描。
在我的真实数据库中,该表包含更多索引列,例如“dynamic_col_1”和“dynamic_col_1_text”。 整个索引文件的大小约为 50 GB。
更多信息:
- 数据库是安装在我的本地计算机上的 Oracle 11g。
- 我使用的是 Windows 7 Enterprise 64bit。
- 整个索引分为 3 个 dbf 文件,大小约为 50GB。
如果有人能告诉我如何让 Oracle 在第一个查询中使用索引,我真的很高兴。 因为第一个查询是被另一个程序用来从数据库中提取数据的,所以很难改变它。所以最好调整一下表格。
提前致谢。
[01.10.2011:更新]
我想我已经找到了问题的解决方案。 dynamic_col_1 和 dynamic_col_1_text 两列都可以为空。在更改表以禁止两列中的“NULL”值并仅为列year 添加新索引后,Oracle 执行快速索引扫描。
优点是现在执行查询需要大约 5 秒,而不是像以前那样需要 1 小时。
【问题讨论】:
-
rowid字段是主键吗? -
请不要调用表中的列 rowid,如果您需要使用实际的 pseudo-column rowid,那您是在要求一个痛苦的世界。
-
@BogdanSahlean 是的,rowid 是主键
-
@Ben 我知道这是个坏名字 ;-)。我的数据库中的列有其他名称。我只是以这种方式命名列以指示主键的位置。