代码之家  ›  专栏  ›  技术社区  ›  Lukman

为Oracle10g中的查询创建索引

  •  2
  • Lukman  · 技术社区  · 16 年前

    我在Oracle10g中的一个特定表中有大约350万条记录,我想查询具有一个空值的特定列的所有记录。

    我的问题是,为了这个查询,是否值得在该列上创建一个索引?使用索引节省的时间会补偿创建索引所花费的时间吗?或者我应该在没有索引的情况下进行查询吗?

    请注意,我没有提前为自己创建索引的选项,如果我只是为查询创建索引,那么之后必须立即删除它。

    P/S:我确实搜索了现有的问题,但找不到我想要的答案。一定要指出我可能遗漏的任何类似问题。

    4 回复  |  直到 16 年前
        1
  •  4
  •   RickNZ    16 年前

    创建索引将比单个查询昂贵得多。如果没有索引,查询只需要扫描表。构建索引还必须扫描表,然后构建并编写索引。

        2
  •  2
  •   Bob Jarvis - Слава Україні    16 年前

    如果我记得正确,Oracle不会为空值编制索引;因此,如果索引中的所有字段都为空,则该行将没有索引项。例如,如果你有一张桌子

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

    并查看不同的键和num_行列。

    这一切的好处在于,如果您有一个查询在特定列中查找空值,那么很可能最终会进行完整的表扫描。我相信聚集索引实际上可以索引空值的条目,但我没有使用它们,所以我不确定。

    我希望这有帮助。

        3
  •  1
  •   Pop    16 年前

    你能用空值在一个分区中结束的方式对表进行分区吗?如果我没有弄错(抱歉,现在不能测试它),空值将转到范围分区表中的maxvalue分区。我认为Oracle可以很好地消除分区,因此只扫描包含空值的分区。您只需要选择一个合适的数字作为前一个分区的高值,以消除大部分或所有不需要的行。

    示例(假设“我的列”是一个数字,而您希望查找空值):

    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)
    );
    

    然后,如果您“从测试表中选择*,其中我的列为空”,执行计划应该只显示正在扫描的分区“空”(完全扫描,但它将主要包含您想要的)。

    如果可以将值从空更新为非空,请记住启用行移动,反之亦然。

        4
  •  1
  •   APC    16 年前

    如果您有企业版,并且您有一个多CPU系统,那么您应该考虑使用并行查询。这是从全表扫描中获得结果的最快方法,尽管它确实有管理开销,而且它确实需要多个CPU的可用性(显然)。

    推荐文章