我有一个包含 3 个表(A、B、C)的数据库,我需要将它们保持在某个阈值大小以下。
A 与 B 和 C 具有一对多关系...
具体来说,A、B、C 有一个名为“g_id”的列,用于建立彼此之间的关系。有点像图结构,其中 A、B、C 是图、节点和边, 分别。
我的目标是:每天,一个脚本将获取此数据库的大小并从这三个表中删除行,直到数据库的总大小缩小回目标大小。
我尝试了以下操作:
获取数据库大小
SELECT TABLE_NAME, round(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) as SIZE_MB FROM information_schema.TABLES WHERE TABLE_NAME in ('A', 'B', 'C') AND TABLE_SCHEMA = DATABASE() ORDER BY SIZE_MB DESC
尝试根据 (A, B, C) 的 g_id 估计每个逻辑分组的大小...
SELECT g_id, SUM(length(col1)) + SUM(constant) as total FROM ( (SELECT A.g_id, A.col1, 22 as constant FROM A) UNION ALL (SELECT B.g_id, B.col1, 22 as constant FROM B) UNION ALL (SELECT C.g_id, C.col1, 22 as constant FROM C) UNION ALL ) ABC GROUP BY g_id ORDER BY g_id;
其中 22 常量只是对每行存储一些固定 bigints、时间戳等的成本的粗略估计...而 col1 是一个可变长度的文本字段。
将第 2 部分加载到内存中后,遍历选定的行并以编程方式将 g_ids 添加到列表中,直到选择了足够多的行进行删除以使数据库恢复到所需的大小。
最后对表 A、B、C...执行 DELETE WHERE g_id IN ({g_ids})
问题是从第 1 部分返回的尺寸似乎产生了一些“间接费用”。例如,当我运行第 1 部分时,数据库的大小约为 3 GB,但当我将第 2 部分中的所有行加起来时,它只有大约 2 GB。随着表格的增长,似乎没有可预测的增长差异。
information_schema.TABLES 和我估计的 SUM 查询报告的这种大小不一致让我删除了比实际需要更多的行。
一些问题:
- 我是否以正确的方式解决这个问题?
- 我的计算有偏差吗?
- 如何确定间接费用?
最佳答案
我认为您考虑删除 记录的做法是错误的。删除记录是一项非常昂贵的操作。
相反,您应该使用表分区。我不太确定逻辑是什么,但所有三个表都可以根据 g_id
进行分区。假设这是按顺序分配的,您可以创建大约一天的新图的批处理。
然后您可以通过删除旧分区来“删除”行。
关于mysql - 确定要删除的 MySQL 行数以达到目标数据库大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52901725/