我有一个名为" 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)同时使用此表。
他们选择一条记录,使用所选数据执行网络请求,然后删除记录。
我从select和delete查询中获得混合执行时间。 delete命令是否锁定表?
这种情况的最佳方法是什么?
SELECT记录+ NETWORK请求+删除记录
SELECT记录+ NETWORK请求+ MARK记录已完成+ DELETE使用cron不时完成记录(我不想要更大的表格)。
注意:队列每分钟都会获得新记录,但INSERT查询不是问题所在。
感谢任何帮助。
答案 0 :(得分:1)
"不要排队,只是这样做"。也就是说,如果任务相当快,最好简单地执行操作而不排队。数据库不能建立良好的排队机制。
DELETE
不会锁定InnoDB表。但是,你可以写一个看起来很顽皮的DELETE
。让我们看看您的实际SQL,以便我们可以改进它。
12M记录?这是一个巨大的积压;什么了?
缩小数据类型,使表格不是千兆字节:
action
只是一小部分可能的值?将其标准化为1字节ENUM
或TINYINT UNSIGNED
。state
- 当然它不需要4字节代码?INDEX(userid)
,因为已经有一个以UNIQUE
开头的索引(userid
)。state
只有几个值,则不会使用该索引。让我们看看你的入队和出队查询,这样我们就可以讨论如何去掉那个索引或者让它“复合”。 (并且很有用)。MAX(id)
的当前值是什么?是否有可能超过INT UNSIGNED
的约40亿的当前限额?state
。告诉我们代码;也许锁和&解锁可以减少侵入性。应该可以运行单个自动提交的UPDATE
来获取一行及其id
。然后,稍后,自动提交DELETE
,影响很小。long_query_time
的值较低)?如果是这样的话,我想知道什么是最差的'查询。在这种情况下,答案可能会令人惊讶。