我有一个非常简单的表,用于记录成员配置文件的访问情况,具有多列键(member_id、visitor_id、month_visited)和更精确的日期。month_visited是一个CHAR(7)列,如下所示:'2013-10‘
每个新的月,我想在另一个表中压缩前一个月的数据,然后删除它。
我的要求很简单:
DELETE FROM visits WHERE month_visited = '2013-10'删除这些行需要很长时间,就像在我的专用服务器上运行几分钟一样。当我只是查询一个简单的SELECT COUNT(*) FROM visits时,情况也是一样。
我有180万份2013-10年的参赛作品。
但这需要很长时间。当我试着
EXPLAIN SELECT * FROM visits WHERE month_visited = "2013-10"它告诉我:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE visits ref idx_month_visited idx_month_visited 21 const 1782148 Using where“用在哪里”,真的吗?
编辑:对不起,我忘了指定我还在month_visited列上添加了一个索引:) (实际上,正如解释所示,但它没有使用它.)
我如何改进那些(显然)简单的查询?我是MySQL的新手,但我不认为执行这些查询需要几分钟的时间是不正常的。
谢谢您的意见!
诚挚的问候,
发布于 2013-11-01 12:57:59
我在这个答复中总结了我的意见。
一般来说,当没有使用索引时,这是因为使用它不会有多大帮助。也就是说,与全表扫描相比,这不会节省太多时间(当索引的基数较低时,就会发生这种情况)。这里的情况似乎是这样的,因为表中的行数与要选择的行数大致相同。在这种情况下,全面扫描通常比使用索引便宜。
同时,删除也是一个“写”操作。索引优化读取,代价是使写入成本更高(因为在写时进行索引重建)。因此,你有一些复杂的指数无助于此,反而加剧了这个问题。当索引缩小要检索的行数时,它是有意义的;否则,它不会提供真正的增益,甚至会增加一些额外的开销。此外,在最好的情况下,索引可以使SELECT更有效。但是它不会使写(插入、更新和删除)工作得更快;相反,它会使它们的性能更差。
所以,你应该试着摆脱那些不是绝对必要的指数。记住,索引是一种权衡,它可能会使读操作(选择)更快,而代价是降低写操作(插入、更新、删除)的速度。这是因为索引必须在写完之后重建。
您可能想试一试:“如果要从一个表中删除许多行,那么使用delete faster之后再使用优化表可能会更快。这将重新构建索引,而不是执行许多索引块合并操作。”Dev.mysql.com/doc/refman/5.0/en/delte.html
还有一种选择(可能有效与否,只需在这里大声思考一下):如果您想从visitss中删除所有行(除了几行),也许您可以在辅助表中插入"WHERE != '2013-10‘“行,截断访问,然后将这些行从aux表中插入回访问,最后截断aux表。不过,正如您所指出的,在此进程运行时,您需要设置某种类型的锁定。
发布于 2013-11-01 00:53:27
只有在条件下使用第一个键组件时,才能使用多列键。在您的情况下,这意味着您的密钥(member_id, visitor_id, month_visited)仅在条件包括
创建一个将month_visited作为第一个组件的键。
https://stackoverflow.com/questions/19719039
复制相似问题