【问题标题】:Why would cardinality of an index in a restored table be different from cardinality in the original table?为什么恢复表中索引的基数与原始表中的基数不同?
【发布时间】:2021-06-09 21:40:53
【问题描述】:

我正在测试一个专有工具,它将 MySQL RDS 中的表转储为 parquet 格式,然后将其恢复到另一个 MySQL RDS。

两个表的行数相同:

mysql> SELECT COUNT(*) FROM fox_owners;
+----------+
| COUNT(*) |
+----------+
|   118950 |
+----------+

在这两种情况下,表格本身的配置方式相同:

mysql> SHOW CREATE TABLE fox_owners;
+------------+-------------------------------------------------------+
| Table      | Create Table                                          |
+------------+-------------------------------------------------------+
| fox_owners | CREATE TABLE `fox_owners` (
  `name` mediumtext,
  `owner_id` bigint NOT NULL,
  PRIMARY KEY (`owner_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+------------+-------------------------------------------------------+

到目前为止一切都很好,对吧?

但是,表格大小不同。 原文:

+----------+----------------------+------------+
| Database | Table                | Size in MB |
+----------+----------------------+------------+
| stam_db  | fox_owners           |    5582.52 |

恢复的:

+----------+----------------------+------------+
| Database | Table                | Size in MB |
+----------+----------------------+------------+
| stam_db  | fox_owners           |    5584.52 |

恢复的大了 2MB! 然而,真正困扰我的是两个表之间索引的基数变化。 原文:

mysql> SHOW INDEX FROM fox_owners;
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| fox_owners |          0 | PRIMARY  |            1 | owner_id    | A         |      118728 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

已恢复:

mysql> SHOW INDEX FROM fox_owners;
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| fox_owners |          0 | PRIMARY  |            1 | owner_id    | A         |      117518 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

为什么基数会从 118728 下降到 117518? 如果恢复的表不如原始表唯一 - 这不是表明该表不同的明显迹象吗?如何验证不同 RDS 数据库中的这 2 个表是否具有相同的内容?

而且它们的基数不应该都是 118950,因为对于具有单个主键列的表,基数必须等于表中的行数?

我已经在两个表上运行了 ANALYZE TABLE,值没有改变。

【问题讨论】:

    标签: mysql indexing amazon-rds parquet cardinality


    【解决方案1】:

    没问题。

    “基数”是通过对表进行少量“随机”探测来确定的。这导致估计。有时估计值会相差两倍甚至更多。 118728 和 117518 异常接近。

    在加载/复制/更改表时,BTree 会被重建。这可能导致 BTree 的块的布局方式发生变化。因此,看到表的大小(在磁盘上)发生变化是正常的。这种情况很少发生 2 倍的变化。

    【讨论】:

    • 感谢您提供清晰有用的答案!如何强制 MySQL 重新计算现有表中的基数?我需要能够证明基数并不像我们想象的那么恒定。
    • 不可能也不实用。基数对优化并不像人们想象的那么重要。 COUNT(*) 准确,但成本高;那是另一个讨论。
    猜你喜欢
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2018-02-18
    • 2022-10-07
    • 2014-11-29
    • 2017-05-22
    相关资源
    最近更新 更多