为什么恢复的 table 中索引的基数与原始 table 中的基数不同?

Why would cardinality of an index in a restored table be different from cardinality in the original table?

我正在测试一种专有工具,可以将 MySQL RDS 中的 table 转储为镶木地板格式,然后将其恢复到另一个 MySQL RDS。

两个 table 的行数相同:

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

table 本身在两种情况下的配置方式相同:

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 |
+------------+-------------------------------------------------------+

到目前为止还不错吧?

但是,table 尺寸不同。 原文:

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

恢复的那个:

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

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

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? 如果恢复后的 table 不如原来的那么独特——这难道不是一个明显的迹象表明这个 table 是不同的吗?我如何验证单独 RDS 数据库中的这 2 个 table 具有相同的内容?

并且无论如何,两者的基数不应该是 118950,因为对于具有单个主键列的 table,基数必须等于 [=42= 中的行数]?

我已经 运行 在两个 table 上分析 TABLE,值没有改变。

没问题。

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

当loading/copying/altering一个table时,BTrees被重建。这可能导致 BTree 块的布局方式发生变化。因此,看到 table 的大小(在磁盘上)发生变化是正常的。很少有 2 倍的变化。