手动删除 Matomo/Piwik 历史日志(MySQL删除大量数据)
不知不觉间,Piwik数据的容量已经达到500GB,虽然并没有感觉到性能有什么影响,但也是时候考虑如何清理其最占空间的访问记录数据了。于是决定拿备份库演练一番:
首先想到的是使用后台的自动清理功能,但是发现其每次10000条的删除能力,对于此等量级的数据可谓是杯水车薪。最后只能翻看源码,得出最基本的两条删除语句。
DELETE FROM `wk_log_conversion` WHERE server_time < '2021-01-01 00:00:00';
DELETE FROM `wk_log_visit` WHERE visit_last_action_time < '2021-01-01 00:00:00';
DELETE FROM `wk_log_link_visit_action` WHERE server_time < '2021-01-01 00:00:00';
至于 wk_log_action
这个表里是被引用的内容,下次遇到相同的引用内容,仍然需要添加一条记录。不删除反而可以确保idaction的唯一性。
至此,我们将遇到第二个问题:
如果要从InnoDB大表中删除许多行,则可能会超出表的锁定表大小InnoDB。也许删除500G的数据需要8个小时左右。
为了避免这个问题,或者只是为了最小化表保持锁定的时间,官方给出以下策略(根本不使用 DELETE):
选择不要删除的行到与原始表具有相同结构的空表中
INSERT INTO t_copy SELECT * FROM t WHERE ... ;
使用RENAME TABLE以原子移动原始表的方式进行,并重新命名拷贝到原来的名称
RENAME TABLE t TO t_old, t_copy TO t;
删除原始表
DROP TABLE t_old;
最终,我们优化查询如下
CREATE TABLE wk_log_conversion_copy LIKE wk_log_conversion;
INSERT INTO wk_log_conversion_copy SELECT * FROM wk_log_conversion WHERE server_time >= '2021-01-01 00:00:00';
RENAME TABLE wk_log_conversion TO wk_log_conversion_old, wk_log_conversion_copy TO wk_log_conversion;
CREATE TABLE wk_log_visit_copy LIKE wk_log_visit;
INSERT INTO wk_log_visit_copy SELECT * FROM wk_log_visit WHERE visit_last_action_time >= '2021-01-01 00:00:00';
RENAME TABLE wk_log_visit TO wk_log_visit_old, wk_log_visit_copy TO wk_log_visit;
CREATE TABLE wk_log_link_visit_action_copy LIKE wk_log_link_visit_action;
INSERT INTO wk_log_link_visit_action_copy SELECT * FROM wk_log_link_visit_action WHERE server_time >= '2021-01-01 00:00:00';
RENAME TABLE wk_log_link_visit_action TO wk_log_link_visit_action_old, wk_log_link_visit_action_copy TO wk_log_link_visit_action;
DROP TABLE wk_log_conversion_old, wk_log_visit_old, wk_log_link_visit_action_old;