我在Oracle 10g的特定表中有大约350万条记录,我想查询一个特定列具有NULL值的所有记录。
我的问题是,为了那个查询的目的,是否值得在该列上创建索引?使用索引节省的时间是否会补偿创建它所需的时间?或者我应该在没有索引的情况下进行查询?
请注意,我没有提前为我创建索引的选项,如果我只为查询创建索引,我必须立即删除它。
p / s:我确实搜索了现有的问题,但找不到我想要的答案。请指出我可能错过的任何类似问题。
答案 0 :(得分:4)
创建索引将比单个查询昂贵得多。如果没有索引,查询将只需要扫描表。构建索引还必须扫描表 - 然后构建并编写索引。
答案 1 :(得分:2)
如果我没记错,Oracle不会为NULL值编制索引;因此,如果进入索引的所有字段都为NULL,则该行没有索引条目。例如,如果您有一个类似
的表格ID NUMBER PRIMARY KEY
FIELD1 NUMBER
FIELD2 NUMBER
带索引
ID_INDEX (ID) PRIMARY KEY
FIELD1_INDEX (FIELD1)
FIELD2_INDEX (FIELD2)
和数据
ID=1 FIELD1=NULL FIELD2=1
ID=2 FIELD1=2 FIELD2=NULL
ID=3 FIELD1=3 FIELD2=3
ID=4 FIELD1=NULL FIELD2=NULL
ID_INDEX中应该有四个条目,但FIELD1_INDEX和FIELD2_INDEX中只有两个条目。您可以通过查询DBA_IND_STATISTICS视图(收集表统计信息后)来验证这一点:
SELECT * FROM DBA_IND_STATISTICS WHERE TABLE_NAME = 'whatever';
并查看DISTINCT KEYS和NUM_ROWS列。
所有这一切的结果是,如果您有一个查询在特定列中查找NULL值,那么很可能您最终会进行全表扫描。我相信聚簇索引实际上可以索引NULL值条目,但我没有使用它们所以我不确定。
我希望这会有所帮助。
答案 2 :(得分:1)
您能否以NULL值在单个分区中结束的方式对表进行分区?如果我没有弄错(抱歉,现在无法测试),NULL值将转到范围分区表中的MAXVALUE分区。我认为Oracle会很好地进行分区消除,因此只扫描包含NULL值的分区。您只需选择一个合适的数字作为前一个分区的高值,以便消除大部分或全部不需要的行。
示例(比如my_column是一个数字,你想找到NULL):
create table test_table (
my_column number,
other_columns ...
)
partition by range (my_column)
(
partition not_null values less than (99999999999999),
partition nulls values less than (MAXVALUE)
);
然后,如果你“从my_column为空的test_table中选择*”执行计划应该只显示正在扫描的分区“空值”(完全扫描,但它主要只包含你想要的内容)。
如果值可以从null更新为非null,请记住启用行移动,反之亦然。
答案 3 :(得分:1)
如果你有Enterprise Edition并且你有一个多CPU系统,那么你应该考虑使用并行查询。这是从全表扫描中获取结果的最快方法,尽管它确实具有管理开销,并且确实需要多个CPU的可用性(显然),