我有一个包含实际用户信息的主表
CREATE TABLE user
(
id bigint NOT NULL
PRIMARY KEY,
updated timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP,
username varchar(40) NULL,
full_name varchar(255) NULL,
biography varchar(512) NULL,
profile_pic_id varchar(40) NULL,
profile_pic_url varchar(255) NULL,
hd_profile_pic_url varchar(255) NULL,
follower_count int NULL,
following_count int NULL,
media_count int NULL,
usertags_count int NULL,
following_tag_count int NULL,
external_url longtext NULL,
reel_auto_archive varchar(255) NULL,
has_biography_translation tinyint(1) NULL,
has_anonymous_profile_picture tinyint(1) NULL,
has_highlight_reels tinyint(1) NULL,
is_business tinyint(1) NULL,
is_active tinyint(1) NULL,
is_verified tinyint(1) NULL,
is_private tinyint(1) NULL,
is_blocked tinyint(1) NULL
)
还有几乎相同的表用于保存历史记录:
CREATE TABLE user_history
(
id int AUTO_INCREMENT
PRIMARY KEY,
user_id bigint NULL,
added timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
username varchar(40) NULL,
full_name varchar(255) NULL,
biography varchar(512) NULL,
profile_pic_id varchar(40) NULL,
profile_pic_url varchar(255) NULL,
hd_profile_pic_url varchar(255) NULL,
follower_count int NULL,
following_count int NULL,
media_count int NULL,
usertags_count int NULL,
following_tag_count int NULL,
external_url longtext NULL,
reel_auto_archive varchar(255) NULL,
has_biography_translation tinyint(1) NULL,
has_anonymous_profile_picture tinyint(1) NULL,
has_highlight_reels tinyint(1) NULL,
is_business tinyint(1) NULL,
is_active tinyint(1) NULL,
is_verified tinyint(1) NULL,
is_private tinyint(1) NULL,
is_blocked tinyint(1) NULL,
CONSTRAINT FK_F19A7E3C5AFE2D44
FOREIGN KEY (user_id) REFERENCES user (id)
)
COLLATE = utf8mb4_unicode_ci;
CREATE INDEX IDX_F19A7E3C5AFE2D44
ON user_history (user_id);
Ang tiger 用于保存历史记录:
CREATE TRIGGER user_update
AFTER UPDATE
ON user
FOR EACH ROW
BEGIN
INSERT INTO `user_history` (`user_id`, `username`, `full_name`, `biography`, `profile_pic_id`,
`profile_pic_url`, `hd_profile_pic_url`, `follower_count`, `following_count`,
`media_count`, `usertags_count`, `following_tag_count`, `external_url`,
`reel_auto_archive`, `has_biography_translation`, `has_anonymous_profile_picture`,
`has_highlight_reels`, `is_business`, `is_active`, `is_verified`, `is_private`,
`is_blocked`, `added`)
VALUES (NEW.id, NEW.username, NEW.full_name, NEW.biography, NEW.profile_pic_id, NEW.profile_pic_url,
NEW.hd_profile_pic_url,
NEW.follower_count, NEW.following_count, NEW.media_count, NEW.usertags_count, NEW.following_tag_count,
NEW.external_url,
NEW.reel_auto_archive, NEW.has_biography_translation, NEW.has_anonymous_profile_picture,
NEW.has_highlight_reels,
NEW.is_business, NEW.is_active, NEW.is_verified, NEW.is_private, NEW.is_blocked, now());
END;
所以我有一些问题:
有什么变体可以提高写入速度以保存历史记录吗? 我尝试通过 LOAD DATA LOCAL INFILE,而不是触发器 - 速度没有提高。
有什么变体可以用较小的数据大小保存历史记录吗? 例如,我想我可以运行一些外部脚本,检查 user_history 数据并为相同的值设置 NULL? 我尝试使用另一个触发器进行保存 - 更大,它在写入之前比较每个值并只写入更改的值 - 但执行时间相当长。 或者有更好的变体将数据差异(可重用)保存到数据库吗?
最佳答案
- 将计数器移至并行表。只需将它们分开也会加快
UPDATE
。 “UPDATE”的内部处理涉及构建整行的副本,以防其他连接访问同一行。 - 此外,不要保留它们的历史记录。我猜想大部分“更新”都在这个领域。
- 将所有
has_%
和is_%
标志组合成一个SET
或TINYINT UNSIGNED
(最多到 8,或SMALLINT UNSIGNED
最多 16)。 - 不要有
has
标志 - 当您需要检查“has”时,只需使用LEFT JOIN
或EXISTS
即可。< - 使
is_%
标志(可能还有其他列)NOT NULL
。一般来说,您应该有意识地决定NULL
对业务逻辑是否有意义,而不是简单地让所有列都NULLable
。
(我的建议适用于所有版本的 MySQL 和 MariaDB。)
关于Mysql优化算法,保存历史更改的变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54863114/