Mysql优化算法,保存历史更改的变体

标签 mysql sql database optimization bigdata

我有一个包含实际用户信息的主表

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;

所以我有一些问题:

  1. 有什么变体可以提高写入速度以保存历史记录吗? 我尝试通过 LOAD DATA LOCAL INFILE,而不是触发器 - 速度没有提高。

  2. 有什么变体可以用较小的数据大小保存历史记录吗? 例如,我想我可以运行一些外部脚本,检查 user_history 数据并为相同的值设置 NULL? 我尝试使用另一个触发器进行保存 - 更大,它在写入之前比较每个值并只写入更改的值 - 但执行时间相当长。 或者有更好的变体将数据差异(可重用)保存到数据库吗?

最佳答案

  • 将计数器移至并行表。只需将它们分开也会加快UPDATE。 “UPDATE”的内部处理涉及构建整行的副本,以防其他连接访问同一行。
  • 此外,不要保留它们的历史记录。我猜想大部分“更新”都在这个领域。
  • 将所有 has_%is_% 标志组合成一个 SETTINYINT UNSIGNED(最多到 8,或 SMALLINT UNSIGNED 最多 16)。
  • 不要有 has 标志 - 当您需要检查“has”时,只需使用 LEFT JOINEXISTS 即可。<
  • 使 is_% 标志(可能还有其他列)NOT NULL。一般来说,您应该有意识地决定 NULL 对业务逻辑是否有意义,而不是简单地让所有列都 NULLable

(我的建议适用于所有版本的 MySQL 和 MariaDB。)

关于Mysql优化算法,保存历史更改的变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54863114/

相关文章:

mysql - 在 DATETIME 字段上按月分组

sql - OpenID、Oauth : Twitter and Facebook 的数据库设计

sql - 在同一个数据库表上进行 2 个几乎相同的选择需要花费不同的时间来执行

mysql - 'LIMIT'参数在sql中是如何工作的?

sql - 如果值为 NULL,则左连接,否则内连接

在 WHERE 中使用 "OR"时 MySQL 不使用索引

sql - 在 SQL/数据库级别计算夏令时 (DST)

mysql - 选择我的问题的陈述

php - MySQL 斜杠和 nl2br

mysql - 使用 MySQL 查询填充 Outlook 正文