MySQL评估索引合理性字段---Cardinality

Cardinality 表示索引的选择性。建立索引的前提是列中的数据是高选择性的。

在MySQL数据库中,可以使用 show index from tableName \G 语句来查看表中创建的索引的信息:

mysql> show index from user_operation_log \G ;
*************************** 1. row ***************************
        Table: user_operation_log
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 8376129
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 2. row ***************************
        Table: user_operation_log
   Non_unique: 1
     Key_name: user_operation_log_ip_IDX
 Seq_in_index: 1
  Column_name: ip
    Collation: A
  Cardinality: 1
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment:
Index_comment:
2 rows in set (0.00 sec)

上面有一个属性Cardinality,可以通过观察它来评估索引是否合理。

Cardinality值非常关键,它表示索引中不重复记录数量的预估值。它是一个预估值,而不是一个准确的值,基本上我们不可能得到一个准确的值。它会估计索引中不重复记录,如果这个相对值很小,可能就要评估索引是否有意义。

Cardinality表示索引的选择性。建立索引的前提是列中的数据是高选择性的。

并不是出现在where 条件中的字段都需要创建索引。

对于那种作为条件查询时,能够过滤掉很多数据的字段(选择性高的列),可以考虑对其创建索引。类似 “性别”、“状态”、“类型”等字段不适合创建索引。

按照“性别”查找时,可取值的范围一般是“M”和“F”。因此sql语句得到的结果可能是该表的50%数据,这个时候添加B+索引没有必要。但如果某个字段的取值范围很广,几乎没有重复,我们称之为高选择性,添加B+树索引很合适。

Cardinality表示索引的选择性。建立索引的前提是列中的数据是高选择性的。

MySQL如何来统计Cardinality信息呢?

MySQL数据库中有各种不同的存储引擎,而每种存储引擎对于B+树的实现方式各不相同,所以对于Cardinality的统计是放在存储引擎层进行的。 

我们需要知道,在生产环境中,索引的更新操作可能是非常频繁的。如果每次索引在发生更新操作时,就对其进行Cardinality值的统计,那么将会给数据库带来很大的负担。如果一张表的数据非常大,假设有上百G,那么统计一次Cardinality信息所需要的时间可能非常长。在生产环境中,也是不能接受的。因此,数据库对于Cardinality的统计是通过采样(Sample)的方法来完成的。 

那么什么时候会更新Cardinality值呢?以及这个值是如何得到的?

更新Cardinality发生在insert和update两个操作中。但是不是每次表中的索引发生insert和update的时候就去更新Cardinality信息。InnoDB存储引擎内部对更新Cardinality信息的策略为:

1) 表中1/16的数据已发生过变化

2) stat_modified_counter>2 000 000 000 (stat_modified_counter是innodb存储引擎中的一个计数器)

第一种策略为自从上一次统计过Cardinality信息之后,表中1/16的数据已经发生过变化,此时就要触发更新Cardinality信息了。

第二种策略考虑到一种情况,如果对表中某一行或者多行的数据频繁地进行更新操作,但是表中的记录数没有增加,发生变化的数据还是这一行或者多行。那么很显然,第一种更新策略无法适用这种情况。这个计数器stat_modified_counter大于2 000 000 000时,同样需要更新Cardinality的信息。

默认Innodb存储引擎对8个叶子节点进行采样。受参数innodb_stats_sample_pages影响。

 手动更新统计值

如果系统运行一段时间之后,我们可以通过执行下面的sql,重新计算cardinality值

当执行语句analyze table、show table status、show index、访问information_schema.tables、访问information_schema.statistics时都会导致innodb存储引擎重新计算cardinality的值。

如果表中数据大,且存在多个辅助索引,以上操作可能会很慢,建议在业务低峰时候执行。

相关SQL语句(innodb引擎): 

show variables like '%innodb_buffer_pool%';

show variables like '%data%';

/**查询表中的 索引信息**/
show index from user_operation_log \G;

/**查询数据页语句  (可以针对一个查询SQL查看加载的数据页有多少)**/
select index_name,count(*) 
from information_schema.INNODB_BUFFER_PAGE 
where INDEX_NAME in('val','primary') and TABLE_NAME like '%user_operation_log%'

group by index_name;

select * from information_schema.INNODB_SYS_TABLES ;

select * from information_schema.INNODB_SYS_COLUMNS ;

select * from information_schema.INNODB_SYS_FIELDS ;

select * from information_schema.INNODB_SYS_INDEXES ;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值