MySQL在哪里不使用索引

Lid*_*oku 2 mysql indexing

我有一个非常简单的表,用于记录成员个人资料上的访问,并带有多列键(member_id,visitor_id,month_visited)和更精确的日期。month_visited是一个类似CHAR(7)的列:'2013-10'

每个新月,我想在另一个表中压缩上个月的数据,然后将其删除。

我的要求很简单:

DELETE FROM visits WHERE month_visited = '2013-10'
Run Code Online (Sandbox Code Playgroud)

删除这些行需要AGES,例如在我的专用服务器上需要几分钟。当我只查询一个简单的SELECT COUNT(*) FROM visits

我在2013-10年度有180万个参赛作品。

但是这需要很长时间。当我尝试

EXPLAIN SELECT * FROM visits WHERE month_visited = "2013-10"
Run Code Online (Sandbox Code Playgroud)

它告诉我:

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
Run Code Online (Sandbox Code Playgroud)

“在哪里使用”,认真吗?

编辑:对不起,我忘记指定仅在month_visited列上也添加了一个索引:)(实际上,正如EXPLAIN所示,但它不使用它...)

如何改善那些(显然)简单的查询?我是MySQL的菜鸟,但执行这些查询需要几分钟的时间,这并不正常。

感谢您的输入!

最好的祝福,

Jua*_*ano 5

我在此答复中总结我的意见。

通常,当不使用索引时,这是因为使用索引没有太大帮助。也就是说,与全表扫描相比,它不会节省太多时间(当索引的基数较低时,这往往会发生)。这似乎是这种情况,因为表中的行数与要选择的行数大致相同。在这种情况下,全面扫描通常比使用索引便宜。

同样,删除是“写”操作。索引以使写入更加昂贵(因为在写入时重建索引)为代价来优化读取。因此,您拥有一些复杂的索引这一事实并没有帮助,反而加剧了这个问题。当索引缩小要检索的行数时,它才有意义。否则,它没有任何实际收益,甚至可能会带来一些额外的开销。同样,在最佳情况下,索引可以使SELECT更有效。但这不会使写入(插入,更新和删除)工作更快。相反,这会使他们的表现更差。

因此,您应该尝试摆脱并非绝对必要的索引。请记住,索引是一个折衷方案,它可能会使读取操作(选择)更快,但会降低写入操作(插入,更新,删除)的速度。这是因为在写操作后必须重建索引。

您可能想尝试一下:“如果要从表中删除许多行,使用DELETE QUICK和OPTIMIZE TABLE可能会更快。这将重建索引而不是执行许多索引块合并操作。” dev.mysql.com/doc/refman/5.0/en/delete.html

还有另一种选择(可能行不行,只是在这里大声思考):如果您想从访问中删除除几行以外的所有行,也许可以将行“ WHERE month!='2013-10'”插入辅助表, TRUNCATE访问,然后将aux表中的行插入到visits中,最后TRUNCATE aux表,但是正如您所指出的,在此过程运行时,您需要进行某种锁定。