【问题标题】:Delete and reuse first auto increment ids from InnoDB table从 InnoDB 表中删除并重用第一个自动增量 ID
【发布时间】:2018-07-27 14:24:09
【问题描述】:

英语不是我的第一语言,所以对于任何语法错误,我提前道歉。

我有以下 MySQL 表(为便于理解而进行了简化):

users (InnoDB - utf8_general_ci):
- usr_Id: int(11) unsigned Auto_Increment
- usr_Username: varchar(50)
- usr_Password: varchar(50)

messages (InnoDB - utf8_general_ci):
- msg_Id: int(11) unsigned Auto_Increment
- msg_UserId: int(11) unsigned
- msg_Date: datetime
- msg_Subject: varchar(50)
- msg_Text: varchar(1024)

还有一个简单的 Web 界面 (PHP),用户可以在其中登录以查看他们的消息:

SELECT msg_Id, msg_Subject FROM messages WHERE msg_UserId = <Logged User Id> ORDER BY msg_Date DESC;

一旦用户点击列表中的消息主题,它会显示一个带有消息的弹出窗口:

SELECT msg_Text FROM messages WHERE msg_Id = <Id From Clicked Message>;

每天凌晨 4 点,cronjob 会自动删除所有超过 3 个月的消息:

DELETE FROM messages WHERE msg_Date < DATE_SUB(NOW(), INTERVAL 3 MONTH);

所以,这是我的问题:这个系统现在测试了大约 5 个月,不到 100 个用户,并且 msg_Id 已经是 91451 !在实际使用时,我预计至少有 2000-5000 个用户!

一旦旧消息被自动删除并且我不使用 msg_Id 来链接不同的表,我想知道是否可以在一段时间后“重用”第一个 id,也许会阻塞服务器几分钟以执行“重置”进程身份证?或者也许有更简单的方法?请问,我有什么选择?

谢谢!

【问题讨论】:

  • 真的没有理由这样做。让这个数字继续增加。它几乎没有机会达到该列的限制。
  • 只要存在自增值较高的记录,服务器将无法重用较低的值。另外戴夫是对的,只需检查 bigint 的最大数量...
  • auto_increment 不得重复使用。不是不应该绝不能。 MySQL 在内部使用它来写入数据。有缝隙没什么不好。 auto_increment 不用于顺序编号,它用于提供唯一编号。为此,它使用顺序增量。如果您的auto_increment 是普通的int,那么您可以使用 42 亿个号码。如果这还不够,您可以将其增加到bigint。如果在接下来的几千年里你每秒不断地插入 1000 个用户,你就不会超过bigint
  • 感谢大家的cmets! @NB,你认为我可以对将 msg_idint 更改为 bigint 并拥有数百万条记录产生重大的存储影响吗?如果 msg_id 不是 auto_increment 怎么办,你能想出一个简单的方法来重用 id 吗?谢谢!
  • 我无法回答您的问题,因为您想重复使用丢失的号码,所有在此发表评论的人都在告诉您不要 .

标签: mysql mariadb auto-increment


【解决方案1】:

甚至不要考虑重用AUTO_INCREMENT 值;这不值得麻烦。甚至不要考虑重新发明这个轮子。它内置了许多不错的功能。

做一些数学运算。如果您认为可能超过 40 亿行,请将 msg_idINT UNSIGNED 更改为 BIGINT UNSIGNED。 100 万 BIGINTs 将比 INT 多占用 4MB。 (如果有二级索引,则更多。)

(可选)不要在列名前加上表名,从而使 SQL 混乱。)

考虑使用PARTITION BY RANGE(TO_DAYS(msg_Date)) 来帮助有效地删除旧数据。

算一算! 91451 * 5000/100 / 5 = 每月只有 1M 行。即使不重用 id,也需要 3 个世纪才能达到 40 亿。

91K 行是一个“小”表。一个有十亿行的表是“大”的,但可行。

需要的索引:

带分区(见this):

PRIMARY KEY(UserId, Date, msg_id),
INDEX(msg_id)

没有分区:

PRIMARY KEY(Date, msg_id),
INDEX(msg_id),
INDEX(UserId, Date)

这些将有效地支持您提供的SELECTs

注意:总有一天,用户会收到数千条消息。您的第一个 SELECT 可能比预期的要慢,或者可能会导致 UI 出现问题。我选择的索引会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-23
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-09-28
    • 2013-09-12
    • 2016-11-20
    相关资源
    最近更新 更多