在一个巨大的表中处理删除/插入/选择

Posted

技术标签:

【中文标题】在一个巨大的表中处理删除/插入/选择【英文标题】:Handling Deletes/Inserts/Select in a huge table 【发布时间】:2013-05-14 19:26:19 【问题描述】:

我有一个约会网站。在这个网站上,我曾经每天向用户发送 10 张照片匹配并将它们存储在结构中作为

SENDER RECEIVER
11      1
12      1
13      1
14      1

我维护了两个月的日志。 用户也可以通过登录我的网站来查看它们。

这意味着有并行插入和选择,这肯定不是问题。

问题是当用户变为非活动状态或删除其 ID 时,我需要从日志中删除 sender='inactive-id' 的所有条目。

日志大小约为 6000 万。 因此,每当这个巨大的表中出现删除查询时,所有选择都会被锁定,并且我的网站正在关闭。

注意我的表是合并 myisam 因为我需要存储 2-3 个月的记录,并且每个月的第一天我都会更改定义

【问题讨论】:

你在使用 MyIsam 引擎吗? @Stephan merge myisam 花时间的部分是实际删除,还是找到要删除的记录?我希望通过一半体面的索引几乎可以立即找到要删除的记录。 把日志转成txt文件,然后删除再写回怎么样? 【参考方案1】:

通常,Table 是被 DELETE 语句锁定的最细粒度的对象。因此,通过使用 MERGE 表,您可以将多个可以独立锁定的对象组合成一个大对象,当 DELETE 命中其任何表时,该对象将被锁定。

MERGE 是针对很少或从不更改的表的解决方案:MERGE Table Advantages and Disadvantages。

你有两个选择:

将锁定的影响降至最低:

小批量删除 在低负载时间运行删除作业 如果不能节省太多空间,请考虑根本不删除 不要删除行,而是将它们标记为“已删除”或已过时并从 SELECT 查询中排除

锁定较小的对象(而不是一次锁定所有表):

从每个基础表中删除多个 Delete 语句 删除 MERGE 定义,从创建 MERGE 的每个基础表中删除数据。但是,我认为您可以在不删除 MERGE 定义的情况下做到这一点。 使用分区。

引用自 mysql 手册:

MERGE 表的替代方法是分区表,它存储 单独文件中单个表的分区。分区启用 一些操作可以更有效地执行,并且不限于 MyISAM 存储引擎。如需更多信息,请参阅Chapter 18, Partitioning。

我强烈主张分区,因为: - 您可以完全自动化您的日志记录/数据保留过程:脚本可以创建新的和删除空分区,将过时的数据移动到不同的表,然后截断该表。 - 强制执行密钥唯一性 - 仅包含要删除的数据的分区被锁定。其他分区上的选择正常运行。 - 搜索同时在所有分区上运行(与 MERGE 一样),但您可以使用 HASH 子分区来进一步加快搜索速度。

但是,如果您认为分区的好处将超过开发成本,那么您可能根本不应该删除这些数据吗?

【讨论】:

【参考方案2】:

我认为最好的解决方案是根据用户 ID 在日志上设置 partitions。这样,当您运行 delete Db 时,只会阻塞一个分区。

【讨论】:

thanx............分区非常明显,但我有大量记录,我也在使用合并表(1merge table=1month=2crore)。在第 4 个月,我改变了定义........同时使用合并和分区是我想的最后一个解决方案 但是你用merge做什么呢? 你也有 1024 个不同分区的限制,我认为 innodb 是最简单和最好的答案 你也可以尝试解决主从复制的问题,但它可能会让你修改相当多的应用程序(连接器和东西)【参考方案3】:

如果您在 Google 上搜索“在大表上删除”,您会得到一些信息丰富的结果。以下是前三个命中:

http://www.dba-oracle.com/t_oracle_fastest_delete_from_large_table.htm

Improving DELETE and INSERT times on a large table that has an index structure

http://www.dbforums.com/microsoft-sql-server/1635228-fastest-way-delete-large-table.html

他们都提到的一种方法是小批量删除,而不是一次全部删除。您说该表包含 2 个月期间的数据。也许您每天单独运行删除语句?

我希望这会有所帮助!

【讨论】:

每当我执行删除操作时,都会发生巨大的锁定。我希望避免【参考方案4】:

如果您使用 InnoDB 并创建 FOREIGN KEY 关系,则可以在删除用户自己时自动删除行:

CREATE TABLE `DailyChoices`(

sender INT(11) 非空, receiver INT(11) 非空, 约束外键 (sender) 引用 users (userid) ON DELETE CASCADE ON UPDATE CASCADE ) 类型 = InnoDB;

【讨论】:

以上是关于在一个巨大的表中处理删除/插入/选择的主要内容,如果未能解决你的问题,请参考以下文章

如何在不让日志文件失控的情况下从巨大的表中删除过期数据?

Excel VBA 在工作表中插入/删除行

MySQL 在从另一个表中选择时插入到具有自动增量的表中

从一个表中删除记录并插入到另一个表中

如何使用特定表中的列作为我需要从中删除、插入或更新数据的表名

如何从1个表中选择许多行并将其插入另一个表中特定行的特定JSONB字段中?但是在单个原始SQL查询中