Mysql复合索引基数在所有字段上都不相同

时间:2013-09-24 08:44:05

标签: mysql indexing cardinality compound-index

我在mysql上创建了一个复合索引,这是我使用的命令: 在DELIVER_SM上创建索引deliver_aid_sid_rcnt_idx(AID,STATUSID,RETRY_CNT)使用BTREE; 奇怪的是,我为每个领域获得了不同的基数值。那是正常的吗?我也创建了其他复合索引,每个字段的基数值是相同的。

+--------------+-----------------+-------------+--------------------------+-------------+
| TABLE_SCHEMA | TABLE_NAME      | COLUMN_NAME | INDEX_NAME               | CARDINALITY |
+--------------+-----------------+-------------+--------------------------+-------------+
| prddb        | DELIVER_SM      | AID         | deliver_aid_sid_rcnt_idx |          28 |
| prddb        | DELIVER_SM      | STATUSID    | deliver_aid_sid_rcnt_idx |         286 |
| prddb        | DELIVER_SM      | RETRY_CNT   | deliver_aid_sid_rcnt_idx |         286 |
+--------------+-----------------+-------------+--------------------------+-------------+
 

1 个答案:

答案 0 :(得分: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树索引的图纸:) 但是我希望你能想象出你头脑中b树索引的图片,就像在这个链接中一样:http://docs.oracle.com/cd/E11882_01/server.112/e25789/indexiot.htm
(顺便说一句,我建议你研究这个材料,它与oracle相关,而不是MySql,但它很好地解释了索引如何工作以及它们是如何组织的)。 enter image description here

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

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

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

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

在这种情况下,c是索引的前导列,MySql“认为”(估计)索引具有9个“顶级”节点,值b占用101个节点“{{{ 1}}“和c在索引中占用407个节点。