我目前正在寻找解决一个基本问题的方案:删除旧记录。
为了说明情况,我有一张表,称之为table1,有少量记录。通常情况下,它是空的,因为它用于中转消息。这些消息在添加到数据库后的两秒内被读取并删除,以便不再读取。
然而,如果接收table1消息的客户端离线,一些消息可能会变成未完成状态,有时数百条,有时数千条,甚至数十万条以上。
这不仅会损害客户端的性能,因为它必须处理大量的消息,而且也会对数据库产生影响,因为它应该保持最少量的记录。
考虑到客户端每秒都会检查新消息,那么删除旧记录的最佳方法是什么?我考虑过添加时间戳,但这样做会影响性能:插入时必须计算时间戳。我尝试过这种方法,但所有查询最终都进入了慢查询日志。
最好的解决方案是什么?我考虑过像检查过去5秒内是否更改了表,如果没有,我们可以确定应该中转的所有消息已经中转完毕,然后可以清除。但是如何实现?
我考虑过每隔几分钟运行一次事件,但我不确定如何实现对select/insert/delete查询没有(或无意义的)影响的内容。
PS:当我发现有些客户端离线,并且有800万条未完成消息时,出现了这种情况。
编辑:
我忘记提到存储引擎是MEMORY,因此所有记录都保存在RAM中。这就是我想要摆脱这些记录的主要原因:因为数百万个不该存在的记录保存在RAM中,会影响系统资源。
以下是错误日志的摘录:
为了说明情况,我有一张表,称之为table1,有少量记录。通常情况下,它是空的,因为它用于中转消息。这些消息在添加到数据库后的两秒内被读取并删除,以便不再读取。
然而,如果接收table1消息的客户端离线,一些消息可能会变成未完成状态,有时数百条,有时数千条,甚至数十万条以上。
这不仅会损害客户端的性能,因为它必须处理大量的消息,而且也会对数据库产生影响,因为它应该保持最少量的记录。
考虑到客户端每秒都会检查新消息,那么删除旧记录的最佳方法是什么?我考虑过添加时间戳,但这样做会影响性能:插入时必须计算时间戳。我尝试过这种方法,但所有查询最终都进入了慢查询日志。
最好的解决方案是什么?我考虑过像检查过去5秒内是否更改了表,如果没有,我们可以确定应该中转的所有消息已经中转完毕,然后可以清除。但是如何实现?
我考虑过每隔几分钟运行一次事件,但我不确定如何实现对select/insert/delete查询没有(或无意义的)影响的内容。
PS:当我发现有些客户端离线,并且有800万条未完成消息时,出现了这种情况。
编辑:
我忘记提到存储引擎是MEMORY,因此所有记录都保存在RAM中。这就是我想要摆脱这些记录的主要原因:因为数百万个不该存在的记录保存在RAM中,会影响系统资源。
以下是错误日志的摘录:
# Query_time: 0.000283 Lock_time: 0.000070 Rows_sent: 0 Rows_examined: 96
SET timestamp=1387199997;
DELETE FROM messages WHERE clientid='100';
[...]
# Query_time: 0.000178 Lock_time: 0.000054 Rows_sent: 0 Rows_examined: 96
SET timestamp=1387199998;
DELETE FROM messages WHERE clientid='14';
所以我想他们确实有一个很小的延迟,但在MySQL中有意义吗?我的意思是,在“现实生活”中,0.0003可能会因其微不足道而完全被忽略,那么对于大约10ms的ping和MySQL连接也可以这样说吗?
SET TIMESTAMP=something
?MySQL 在 SQL 语句中通过NOW()
访问了一个完美的内部时间戳设置。此外,您的第一次查询时间是 283 纳秒,锁定时间(独占访问时间)为 70 纳秒。这似乎不是很多。 - O. Jones