【问题标题】:crazy cardinality counts for show table status显示表状态的疯狂基数
【发布时间】:2012-03-24 03:12:56
【问题描述】:

迭代1:

mysql> show table status LIKE "mybigusertable";
+-----------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+--------------------------+
| Name            | Engine | Version | Row_format | Rows    | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment                  |
+-----------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+--------------------------+
| mybigusertable | InnoDB |      10 | Compact    | 3089655 |           1686 |  5209325568 |               0 |    797671424 |         0 |        3154997 | 2011-12-04 03:46:43 | NULL        | NULL       | utf8_unicode_ci |     NULL |                | InnoDB free: 13775872 kB | 
+-----------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+--------------------------+

mysql> show index from mybigusertable;
+-----------------+------------+-----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table           | Non_unique | Key_name        | Seq_in_index | Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------------+------------+-----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| mybigusertable |          0 | PRIMARY         |            1 | someid         | A         |     3402091 |     NULL | NULL   |      | BTREE    

迭代 2

mysql> show index from mybigusertable;
+-----------------+------------+-----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table           | Non_unique | Key_name        | Seq_in_index | Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------------+------------+-----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| mybigusertable |          0 | PRIMARY         |            1 | someid         | A         |     2811954 |     NULL | NULL   |      | BTREE    

以上两者之间的时间小于5秒。为什么每次调用show index都会有如此大的差异?

这只发生在这张桌子上,我检查了几张更大的桌子,每次访问它们时都显示相同的数字

仅供参考:

mysql> select count(*) from mybigusertable;
+----------+
| count(*) |
+----------+
|  3109320 | 
+----------+
1 row in set (4 min 34.00 sec)

几个问题:

  1. 为什么基数变化如此之大,这真的很重要吗?
  2. Optimize Table 有多重要?它会使查询更快吗?

【问题讨论】:

    标签: mysql database optimization query-optimization cardinality


    【解决方案1】:

    我认为问题源于 InnoDB 如何处理表元数据。

    InnoDB 倾向于使用某种形式的搜索深度近似(由 optimizer_search_depth 规定),这需要深入研究索引以猜测基数。

    尝试关闭innodb_stats_on_metadata

    SET GLOBAL innodb_stats_on_metadata = 0;
    

    这将有助于更快地读取元数据并稳定查询执行计划。

    更新 2012-03-06 11:55 EST

    对 InnoDB 表执行 OPTIMIZE TABLE 是没有用的,因为一旦您这样做以尝试编译索引统计信息,如果 innodb_stats_on_metadata 仍为 1,它往往会被重新读取。I wrote about this in the DBA StackExchange 早在 2011 年 6 月。

    更新 2012-03-06 11:59 EST

    好的,既然您使用的是 MySQL 5.0.77,那么 OPTIMIZE TABLE 对 InnoDB 中的索引统计信息再生来说只是陈旧的无用。

    OPTIMIZE TABLE 和 ANALYZE TABLE 仅适用于 MyISAM。

    【讨论】:

    • 嗯,所以运行优化或分析对我没有任何好处! InnoDB 有类似的东西吗?查询非常缓慢,EXPLAIN 显示了非常好的数字,需要扫描几百行等,但运行相同的查询是一场噩梦。一个简单的计数需要 5 分钟在一个 3+ mil 行的表上。
    【解决方案2】:

    MySQL 通过从索引中随机抽取页面来确定索引的基数。页面具有不同的记录数和分布。

    对于基数不变的索引,很可能该索引适合单个页面,或者页面分布均匀(例如,来自优化表)。

    如果计数差异很大,您可以考虑优化表以重新分配记录。这将帮助 MySQL 选择最佳索引。

    【讨论】:

    • 我们至少一年没有优化这个表(大约 150 万+条记录) 唯一的问题是应用程序是高可用性的应用程序,主要停机时间很危险。优化期间的停机时间是可以的,只是不想让事情变慢,因为我过去看到优化实际上减慢了许多查询
    • 只要数字在同一个球场,或者您不依赖 MySQL 选择最佳索引(在两个或多个具有相似基数的索引之间),那么就没有什么可担心的.
    猜你喜欢
    • 2016-07-03
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多