一、基數(shù)是啥?
Cardinality指的就是MySQL表中某一列的不同值的數(shù)量。
如果這一類是唯一索引,那基數(shù) = 行數(shù)。
如果這一列是sex,枚舉類型只有男女,那它是基數(shù)就是2
Cardinality越高,列就越有成為索引的價值。MySQL執(zhí)行計劃也會基于Cardinality選擇索引。
通過下面的方式可以看到表中各列的基數(shù)。

比如這個經(jīng)典的例子:
有一列為sex,那對于sex列中存儲的值來說 非男即女,它的基數(shù)最大就是2。
那也就完全沒有必要為sex建立索引。因為,為了提升你基于sex的查詢速度,MySQL會為你選擇的這個新索引創(chuàng)建一棵全新的B+Tree。但你sex只有兩種值,對于MySQL來說,即使它為你指定的列建立了B+Tree索引,真正執(zhí)行查詢時,最多進行一次二分查詢,剩下的操作只能是遍歷,所以為sex創(chuàng)建索引意義不大。
二、InnoDB更新基數(shù)的時機?
參數(shù):innodb_stats_auto_recalc控制MySQL是否主動重新計算這些持久性的信息。默認(rèn)為1表示true,0表示false。
默認(rèn)情況下當(dāng)表中的行變化超過10%時,重新計算基數(shù)信息。
三、基數(shù)是估算出來
基數(shù)并不會實時更新!而且它是通過采樣估算出來的值!
至于基數(shù)的公式是怎樣的,可能并不重要。
重要的是你得知道,他是通過隨機采樣數(shù)據(jù)頁的方式統(tǒng)計出來的一個估算值。
而且隨機采樣的頁數(shù)可以通過參數(shù)innodb_stats_persistent_sample_pages 設(shè)置,默認(rèn)值是20。
這就意味著 基數(shù)值并不準(zhǔn)確,甚至你每次計算的結(jié)果相擦還是蠻大的。
四、持久化基數(shù)
可以通過參數(shù)innodb_stats_persistent 控制是否持久化基數(shù),默認(rèn)為off。
當(dāng)然你可以為一個單獨的表設(shè)置 STATS_PERSISTENT=1 那么它的 innodb_stats_persistent將自動被啟用。
開啟它的好處是:重啟MySQL不會再重復(fù)計算這個值,加快重啟速度。
五、如何主動更新基數(shù)?
執(zhí)行下面的SQL時都會觸發(fā)InnoDB更新基數(shù)(即使你并沒有意識到它會更新基數(shù))。
所以盡量選擇一個業(yè)務(wù)低峰期
analyze table tableName;

如果因為采樣的數(shù)量太少了,計算的基數(shù)錯的離譜。那很可能會導(dǎo)致MySQL的優(yōu)化器選錯索引。這是你可以將這個值適當(dāng)調(diào)大。但是增加 太多可能會導(dǎo)致 ANALYZE TABLE運行緩慢。
反之, ANALYZE TABLE運行太慢。你可以適度調(diào)整參數(shù)innodb_stats_persistent_sample_pages 的值。但是這又可能導(dǎo)致基數(shù)計算的不準(zhǔn)確。
如果沒有辦法平衡兩者的關(guān)系。可以考慮減少表中索引列的數(shù)量或限制分區(qū)的數(shù)量以降低 ANALYZE TABLE復(fù)雜性。表的主鍵中的列數(shù)也很重要,因為主鍵列被附加到每個非唯一索引中。
參考:
https://dev.mysql.com/doc/refman/5.7/en/innodb-persistent-stats.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-analyze-table-complexity.html
以上就是淺析MySQL的基數(shù)統(tǒng)計的詳細(xì)內(nèi)容,更多關(guān)于MySQL 基數(shù)統(tǒng)計的資料請關(guān)注腳本之家其它相關(guān)文章!
您可能感興趣的文章:- Mysql臟頁flush及收縮表空間原理解析
- 推薦幾款MySQL相關(guān)工具
- 淺析MySQL的lru鏈表
- MySQL的查詢緩存和Buffer Pool
- mysql 遞歸查找菜單節(jié)點的所有子節(jié)點的方法
- MySQL的表空間是什么
- MySQL慢查詢?nèi)绾味ㄎ辉斀?/li>
- MySQL的Flush-List和臟頁的落盤機制