【问题标题】:MySQL query takes longer with indices?MySQL查询需要更长的索引吗?
【发布时间】:2011-01-16 22:25:08
【问题描述】:

我有一个 MySQL InnoDB 表 events,有 3 行:

event_id  ---> int
start     ---> long
end       ---> long

我写了一个简单的查询来获取某个范围内与另一个事件冲突的所有事件:

select a.* from events a, events b 
where a.event_id != b.event_id and 
      a.start < b.end and 
      b.start < a.end

该表有大约 10K 行,执行时间大约为 2 秒。在尝试调整表格以提高性能时,我在 startend 列上添加了索引。出于某种原因,这显着地降低了性能 5 倍。有谁知道或有任何想法,为什么添加这些索引会对性能造成如此糟糕的影响?

【问题讨论】:

    标签: sql mysql performance innodb


    【解决方案1】:

    MySQL 会查看所涉及的列,并误以为索引将有助于改进查询。但问题是索引解决了起始部分,但需要解析回记录 ID 以解决 a.event_id != b.event_id,这本身就是一项昂贵的操作。

    没有索引会强制进行交叉连接和过滤,尽管这可能会膨胀到大量临时记录,但实现起来要简单得多。

    如果您的查询被 a 或 b 上的某个范围与 start-end 绑定,和/或表大于 10k,它可能会变成完全不同的画面。

    如果您需要保留索引,您可以强制特定查询(如果您知道这有帮助)忽略索引:

    select a.*
    from events a ignore index (index1)
    cross join events b ignore index (index1)
    where a.event_id != b.event_id and 
          a.start < b.end and 
          b.start < a.end
    

    假设索引名为 index1。在任何情况下,通过在查询前添加“EXPLAIN”以显示 MySQL 如何收集结果(不带索引、带索引、带索引但被忽略)来查看 MySQL 在每种情况下所做的事情总是有帮助的

    【讨论】:

    • 有没有办法构造查询,以便我可以保留索引(它们将帮助其他查询)但仍然执行交叉连接和过滤?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多