关于 B 树索引中不同值的最大数量的简单问题

Trivial question about max number of distinct values in a B-tree index

我正在尝试了解索引。我查看了工作中数据库中使用的实际索引。

我查看了两个随机索引:

SELECT
INDEX_NAME, INDEX_TYPE, LEAF_BLOCKS, DISTINCT_KEYS 
FROM ALL_INDEXES
WHERE TABLE_NAME = 'TRANS'
AND INDEX_NAME IN ('TRANS_PK','TRANS_ORD_NO')

这给出:

INDEX_NAME  | INDEX_TYPE | LEAF_BLOCKS | DISTINCT_KEYS |
TRANS_PK    | NORMAL     | 13981       |    3718619    | 
TRANS_ORD_NO| NORMAL     | 17052       |    43904      |

这对我来说毫无意义;与实际 table 不同的 (column_name) 不应该产生相同的数字吗?它没有!

SELECT COUNT(DISTINCT ORD_NO) FROM trans

..给出 20273

TRANS_PK 是名为 NO.

的列的索引
SELECT COUNT(distinct NO) FROM trans

... 给出 4 328 622

我没有得到什么? select distinct 的结果应与 "distinct keys" - ALL_INDEXES- table?

中的列相同

字典视图(包括 ALL_INDEXES )没有 real-time 数据,但新的统计值会在分析期间刷新,并随着时间的推移变得陈旧。

也在这里检查:https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-index-design-guide?view=sql-server-2017 "Each index row contains a key value and a pointer to either an intermediate level page in the B-tree, or a data row in the leaf level of the index." - 所以在数据指针之上你还有许多 cross-level 叶子。

可以使用 DBMS_STATS.GATHER_INDEX_STATS() 过程收集索引统计信息。下面的示例显示了如何在插入行和收集索引统计信息后更新 DISTINCT_KEYS 值。请注意,默认情况下,Oracle 会从索引中抽取一定百分比的数据,因此 DISTINCT_KEYS 可能无法反映索引中不同键的实际数量。请参阅下面 link 中的 estimate_percent 参数。

https://docs.oracle.com/database/121/ARPLS/d_stats.htm#ARPLS68575

SQL> CREATE TABLE foo AS SELECT LEVEL id FROM dual CONNECT BY LEVEL <= 5;

Table FOO created.

SQL> CREATE INDEX foo_idx ON foo(id);

Index FOO_IDX created.

SQL> SELECT * FROM foo;

        ID
----------
         1
         2
         3
         4
         5

SQL> SELECT distinct_keys FROM all_indexes WHERE table_name = 'FOO';

DISTINCT_KEYS
-------------
            5

SQL> INSERT INTO foo VALUES(6);

1 row inserted.

SQL> INSERT INTO foo VALUES(7);

1 row inserted.

SQL> COMMIT;

Commit complete.

SQL> 
SQL> SELECT distinct_keys FROM all_indexes WHERE table_name = 'FOO';

DISTINCT_KEYS
-------------
            5

-- Here's where we gather the statistics
SQL> EXECUTE DBMS_STATS.GATHER_INDEX_STATS('MYSCHEMA', 'FOO_IDX');

PL/SQL procedure successfully completed.

SQL> SELECT distinct_keys FROM all_indexes WHERE table_name = 'FOO';

DISTINCT_KEYS
-------------
            7