0

我在 mysql 上创建了一个复合索引,这是我使用的命令:create index deliver_aid_sid_rcnt_idx on DELIVER_SM(AID,STATUSID,RETRY_CNT) USING BTREE; 奇怪的是我为每个字段得到了不同的基数值。这正常吗?我还创建了其他复合索引,并且每个字段的基数值是相同的。

+--------------+------+-------------+-- ------------+-------------+
| 表模式 | 表名 | COLUMN_NAME | 索引名称 | 基数 |
+--------------+------+-------------+-- ------------+-------------+
| 数据库 | DELIVER_SM | 援助 | Deliver_aid_sid_rcnt_idx | 28 |
| 数据库 | DELIVER_SM | 状态ID | Deliver_aid_sid_rcnt_idx | 286 |
| 数据库 | DELIVER_SM | 重试_CNT | Deliver_aid_sid_rcnt_idx | 286 |
+--------------+------+-------------+-- ------------+-------------+
 
4

1 回答 1

1

索引基数不是列的不同值的数量,而是 b 树索引中的节点数量。

考虑下面的例子:

CREATE TABLE abc(   a int, b int, c int );

set @x = 0;
INSERT INTO abc( a, b, c ) 
SELECT (@x:=@x+1),
       round( @x / 10 ),
       round( @x / 100 )
FROM information_schema.columns
LIMIT 421;

CREATE INDEX ix1 ON abc( a, b, c );
CREATE INDEX ix2 ON abc( c, b, a );

ANALYZE TABLE abc;

和显示索引基数的查询:

SELECT COUNT( distinct a) a,
       COUNT( distinct b) b,
       COUNT( distinct c) c,
       COUNT( * )
FROM abc;

SELECT table_name, index_name, column_name, cardinality
FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = 'abc' AND index_name = 'ix1';

SELECT table_name, index_name, column_name, cardinality
FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = 'abc' AND index_name = 'ix2';


看这个演示看看结果:http

://www.sqlfiddle.com/#!2/b5987/ 1 该表有 421 行。
a有 421 个不同的值。
b有 43 个不同的值。
c有 5 个不同的值。

我是一个可怜的抽屉,所以我不在这里附上这些 b-tree 索引的图 :)
但我希望你能在脑海中想象一个 b-tree 索引的图片,就像在这个链接中一样:http://docs。 oracle.com/cd/E11882_01/server.112/e25789/indexiot.htm
(顺便说一句,我建议您学习此材料,它与 oracle 相关,而不是 MySql,但它很好地解释了索引如何工作以及它们是如何组织的)。 在此处输入图像描述

对于ix1 ON abc( a, b, c )索引 MySql 显示以下基数:
a --> 407
b --> 407
c --> 407

请记住,基数不是精确值,而是估计值。

a是索引中的前导列(这是具有最多不同值的列),因此它在索引中创建了大量的顶级节点。剩余的列(它们的值)也存储在这些顶级索引节点中(或者可能是“下方)。

悬停ix2 ON abc( c, b, a )估计基数的值是不同的:
c --> 9
b --> 101
a --> 407

在这种情况下,c索引的前导列在哪里,MySql“认为”(估计)索引有9个“顶级”节点,b取101个节点“下c”的值,a

于 2013-09-24T19:37:53.833 回答