gpt4 book ai didi

oracle - Oracle 何时为空列值建立索引?

转载 作者:行者123 更新时间:2023-12-02 18:07:49 25 4
gpt4 key购买 nike

我曾经认为当其中一个列值为空时,Oracle 不会索引一行。

一些简单的实验表明情况并非如此。我能够运行一些查询,意外地仅访问索引,即使某些列可以为空(这当然是一个令人愉快的惊喜)。

谷歌搜索导致一些博客的答案相互矛盾:我读到,除非所有索引列都为空,否则行会被索引,并且除非前导列,否则行会被索引索引的值为 null。

那么,什么情况下一行不会进入索引呢?这个 Oracle 版本是否特定?

最佳答案

如果任何索引列包含非空值,则该行将被索引。正如您在下面的示例中看到的,只有一行没有被索引,并且该行在两个索引列中都有 NULL。您还可以看到,当前导索引列具有 NULL 值时,Oracle 肯定会对行建立索引。

SQL> create table big_table as
2 select object_id as pk_col
3 , object_name as col_1
4 , object_name as col_2
5 from all_objects
6 /

Table created.

SQL> select count(*) from big_table
2 /

COUNT(*)
----------
69238

SQL> insert into big_table values (9999990, null, null)
2 /

1 row created.

SQL> insert into big_table values (9999991, 'NEW COL 1', null)
2 /

1 row created.

SQL> insert into big_table values (9999992, null, 'NEW COL 2')
2 /

1 row created.

SQL> select count(*) from big_table
2 /

COUNT(*)
----------
69241

SQL> create index big_i on big_table(col_1, col_2)
2 /

Index created.

SQL> exec dbms_stats.gather_table_stats(user, 'BIG_TABLE', cascade=>TRUE)

PL/SQL procedure successfully completed.


SQL> select num_rows from user_indexes where index_name = 'BIG_I'
2 /

NUM_ROWS
----------
69240

SQL> set autotrace traceonly exp
SQL>
SQL> select pk_col from big_table
2 where col_1 = 'NEW COL 1'
3 /

Execution Plan
----------------------------------------------------------
Plan hash value: 1387873879

-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 4 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 2 | 60 | 4 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | BIG_I | 2 | | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("COL_1"='NEW COL 1')

SQL> select pk_col from big_table
2 where col_2 = 'NEW COL 2'
3 /

Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771

-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 176 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 2 | 60 | 176 (1)| 00:00:03 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("COL_2"='NEW COL 2')

SQL> select pk_col from big_table
2 where col_1 is null
3 and col_2 = 'NEW COL 2'
4 /

Execution Plan
----------------------------------------------------------
Plan hash value: 1387873879

-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 53 | 4 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 1 | 53 | 4 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | BIG_I | 2 | | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("COL_1" IS NULL AND "COL_2"='NEW COL 2')
filter("COL_2"='NEW COL 2')

SQL> select pk_col from big_table
2 where col_1 is null
3 and col_2 is null
4 /

Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771

-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 53 | 176 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 1 | 53 | 176 (1)| 00:00:03 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("COL_1" IS NULL AND "COL_2" IS NULL)

SQL>

此示例在 Oracle 11.1.0.6 上运行。但我非常有信心它适用于所有版本。

关于oracle - Oracle 何时为空列值建立索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1230786/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com