删除超过15分钟的所有条目

时间:2011-07-10 12:51:10

标签: mysql performance

我有一张桌子,每分钟可以获得10-15,000个参赛作品。每个人在进入时都标有当前时间戳。该表是MEMORY表,因为丢失数据不是问题。

每分钟,我都有一个运行以下查询的脚本:

DELETE FROM tracker WHERE post_time < DATE_SUB(NOW(), INTERVAL 15 MINUTE)

此查询大约需要1-2秒才能运行,这也不错,但似乎这种类型的查询(删除早于X的所有内容)在运行时应该能够更快地执行对MEMORY表。它也有相应的CPU尖峰,每分钟像拇指一样突出。

我可以对查询进行任何优化以更有效地运行此查询吗?

3 个答案:

答案 0 :(得分:6)

与往常一样,您应该查看查询计划,并在此处发布。您可以通过发出EXPLAIN DELETE FROM tracker WHERE post_time < DATE_SUB(NOW(), INTERVAL 15 MINUTE)

来实现这一目标

现在,问题可能是DELETE查询无法使用索引,并且必须循环遍历所有行。

即使您已经拥有post_time的索引,也可能不会使用它,因为默认情况下MEMORY表上的索引是哈希索引。 散列索引只能用于等式检查,而不能用于post_time < DATE_SUB(NOW(), INTERVAL 15 MINUTE)

等范围

在post_time列上创建BTREE索引

CREATE INDEX post_time_idx ON tracker (post_time) USING BTREE;

答案 1 :(得分:1)

在post_time上制作索引。如果匹配post_time < DATE_SUB(NOW(), INTERVAL 15 MINUTE)的行只占整个表的一小部分,那么这应该会加速很多事情。

答案 2 :(得分:1)

如果您的表中的数据永远不会超过15分钟,则可以使用比DATETIME更小的数据类型来存储时间戳。根据您关注的粒度,您可以使用非常小型数据类型...使用 SMALLINT ,您可以存储'午夜以来的分钟'。如果您愿意失去更多粒度,可以使用 TINYINT 15分钟的粒度。当然,这需要稍微复杂的逻辑,以便“在午夜之后”处理案件......

DELETE FROM tracker
WHERE (
    EXTRACT(DAY_MINUTE FROM NOW()) > 15
    AND post_time < EXTRACT(DAY_MINUTE FROM NOW())
) OR (
    post_time < EXTRACT(DAY_MINUTE FROM NOW()) < 15
    AND post_time < EXTRACT(DAY_MINUTE FROM NOW()+60)
)

优点是您必须阅读和比较的数据要小得多,因此可以更快地处理。如果您将数据存储在磁盘上,磁盘I / O比内存带宽要重要得多,那么这会产生更大的差异。

此外,对于一个只有10-15k行的表和一个正确的索引,我怀疑这会产生任何明显的差异 - 无论是在磁盘上还是在内存中。