MySQL 性能 - 从大 table 中选择和删除

MySQL performance - Selecting and deleting from a large table

我有一个很大的 table,叫做 "queue"。它现在有 1200 万条记录。

CREATE TABLE `queue` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `userid` varchar(64) DEFAULT NULL,
  `action` varchar(32) DEFAULT NULL,
  `target` varchar(64) DEFAULT NULL,
  `name` varchar(64) DEFAULT NULL,
  `state` int(11) DEFAULT '0',
  `timestamp` int(11) DEFAULT '0',
  `errors` int(11) DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_unique` (`userid`,`action`,`target`),
  KEY `idx_userid` (`userid`),
  KEY `idx_state` (`state`)
) ENGINE=InnoDB;

多名 PHP 名工人 (150) 同时使用此 table。

他们 select 一条记录,使用 selected 数据执行网络请求,然后删除该记录。

我从 select 和删除查询中得到混合执行时间。删除命令是否锁定 table?

这种情况的最佳方法是什么?

  1. SELECT记录+NETWORK请求+DELETE记录

  2. SELECT 记录 + 网络请求 + 将记录标记为已完成 + 不时使用 cron 删除已完成的记录(我不想要更大的 table) .

注意:队列每分钟获取新记录,但 INSERT 查询不是这里的问题。

感谢任何帮助。

"Don't queue it, just do it"。也就是说,如果任务相当快,最好只是执行操作而不是排队。数据库没有很好的排队机制。

DELETE 不锁定 InnoDB table。但是,你可以写一个看起来很调皮的DELETE。让我们看看您的实际 SQL,以便我们改进它。

12M 条记录?这是一个巨大的积压;怎么了?

缩小数据类型,使 table 不是千兆字节:

  • action只是一小部分可能的值?将其标准化为 1 字节 ENUMTINYINT UNSIGNED.
  • 同上 state -- 它肯定不需要 4 字节代码吗?
  • 不需要INDEX(userid),因为已经有一个以userid开头的索引(UNIQUE)。
  • 如果state只有几个值,索引将不会被使用。让我们看看您的入队和出队查询,以便我们可以讨论如何摆脱该索引或使其成为 'composite'(并且有用)。
  • MAX(id)的当前值是多少? INT UNSIGNED 是否有超过您目前约 40 亿的限制?
  • PHP如何使用队列?它是否通过 InnoDB 事务挂在项目上?这打败了任何并行性!或者它会改变 state。向我们展示代码;也许锁定和解锁可以减少侵入性。应该可以 运行 一个自动提交的 UPDATE 来获取一行及其 id。然后,稍后,执行自动提交 DELETE,影响很小。
  • 我没有看到用于抓取挂起项目的良好索引。再一次,让我们看看代码。
  • 150 似乎很多 -- 您是否尝试过 更少的?他们可能互相绊倒。
  • Slowlog 是否打开(long_query_time 的值较低)?如果是这样,我想知道 'worst' 查询是什么。在这种情况下,答案可能会令人惊讶。