手动删除Matomo历史日志

不知不觉间,Matomo数据的容量已经达到500GB,虽然并没有感觉到性能有什么影响,但也是时候考虑如何清理其最占空间的访问记录数据了。于是决定拿备份库演练一番:

首先想到的是使用后台的自动清理功能,但是发现其每次10000条的删除能力,对于此等量级的数据可谓是杯水车薪。最后只能翻看源码,得出最基本的两条删除语句。

DELETE FROM `matomo_log_conversion` WHERE server_time < '2023-08-20 00:00:00';
DELETE FROM `matomo_log_visit` WHERE visit_last_action_time < '2023-08-20 00:00:00';
DELETE FROM `matomo_log_link_visit_action` WHERE server_time < '2023-08-20 00:00:00';

至于 matomo_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 matomo_log_conversion_copy LIKE matomo_log_conversion;
INSERT INTO matomo_log_conversion_copy SELECT * FROM matomo_log_conversion WHERE server_time >= '2023-08-20 00:00:00';
RENAME TABLE matomo_log_conversion TO matomo_log_conversion_old, matomo_log_conversion_copy TO matomo_log_conversion;
CREATE TABLE matomo_log_visit_copy LIKE matomo_log_visit;
INSERT INTO matomo_log_visit_copy SELECT * FROM matomo_log_visit WHERE visit_last_action_time >= '2023-08-20 00:00:00';
RENAME TABLE matomo_log_visit TO matomo_log_visit_old, matomo_log_visit_copy TO matomo_log_visit;
CREATE TABLE matomo_log_link_visit_action_copy LIKE matomo_log_link_visit_action;
INSERT INTO matomo_log_link_visit_action_copy SELECT * FROM matomo_log_link_visit_action WHERE server_time >= '2023-08-20 00:00:00';
RENAME TABLE matomo_log_link_visit_action TO matomo_log_link_visit_action_old, matomo_log_link_visit_action_copy TO matomo_log_link_visit_action;
DROP TABLE matomo_log_conversion_old, matomo_log_visit_old, matomo_log_link_visit_action_old;
点赞