前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL如何评估索引的合理性?

MySQL如何评估索引的合理性?

作者头像
SEian.G
发布2022-03-30 10:16:34
4240
发布2022-03-30 10:16:34
举报
文章被收录于专栏:SEian.G学习记录SEian.G学习记录

我们都知道,在关系型数据库中,索引的存在是非常重要的,但是不合理的索引反而会影响到业务的性能,那怎么才能合理的设计索引也是业务高效访问数据库需要考虑的?如何才能评估索引创建的合理呢?今天我们给出其中一个评估指标:Cardinality

在MySQL数据库中,如何查看表的索引情况呢?

执行show index from tb_name;命令即可;如下所示:

代码语言:javascript
复制
mysql >show index from sbtest1\G
*************************** 1. row ***************************
        Table: sbtest1
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 48229276
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
*************************** 2. row ***************************
        Table: sbtest1
   Non_unique: 1
     Key_name: k_1
 Seq_in_index: 1
  Column_name: k
    Collation: A
  Cardinality: 9172199
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
2 rows in set (0.01 sec)

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

那什么是Cardinality值?

官方文档解释:

An estimate of the number of unique values in the index. To update this number, run ANALYZE TABLE or (for MyISAM tables) myisamchk -a. Cardinality is counted based on statistics stored as integers, so the value is not necessarily exact even for small tables. The higher the cardinality, the greater the chance that MySQL uses the index when doing joins.

并不是在所有的查询条件中出现的列都需要添加索引。

对于什么时候添加B+树索引,一般的经验是,在访问表中很少一部分数据时使用B+树索引才有意义。例如,对于性别字段、地区字段、类型字段、状态字段,它们的可取值范围很小,成为低选择性的列。如:

select * from student where sex=’F’

按照性别查找时,可取值的范围一般是“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的值。如果表中数据大,且存在多个辅助索引,以上操作可能会很慢,建议在业务低峰时候执行。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA的辛酸事儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档