低基数索引仍然会降低查询速度

时间:2013-05-03 21:18:50

标签: mysql indexing innodb

使用带有InnoDB的MySQL 5.5。 有一个像

这样的查询
    SELECT
        count(distinct a.thing_id) as new_thing_count,
        sum(b.price) as new_thing_spend
    FROM thing ii
    LEFT OUTER JOIN thing a
        ON a.customer_id = ii.customer_id
        AND a.created_at >= '2013-01-01'
        AND a.created_at <= '2013-03-31'
    JOIN whatsit b
        ON b.whatsit_id = a.original_whatsit_id
    WHERE ii.customer_id = 3

其中

  • thing的基数约为25k,其中3.5k属于客户3
  • 有12个可能customer_id s

现在,当我使用customer_id上的索引运行此查询时,大约需要10秒钟。当我删除索引时,需要.03秒。

我无法弄清楚为什么会这样。这是没有索引的解释结果:

1   SIMPLE  ii  ALL                 24937   Using where
1   SIMPLE  a   ALL                 24937   Using where; Using join buffer
1   SIMPLE  b   eq_ref  PRIMARY PRIMARY 4   db.a.original_whatsit_id    1   

这里是索引(thing_customer

1   SIMPLE  ii  ref thing_customer  thing_customer  4   const   3409    Using index
1   SIMPLE  a   ref thing_customer  thing_customer  4   const   3409    Using where
1   SIMPLE  b   eq_ref  PRIMARY PRIMARY 4   db.a.original_whatsit_id    1   

有人可以帮我解释一下为什么这个索引在逻辑上似乎不应该减慢这么多的东西吗?

1 个答案:

答案 0 :(得分:2)

当您的数据库引擎决定读取索引时,它会按顺序逐个读取行。这可以使它读取磁盘页面2中的一行,第4页中的另一行,第1页中的另一行,第2页中的下一行等。

有时,反复来回是指数没有帮助 - 恰恰相反。

如果数据库引擎在生成查询计划时收集和分析表上的统计信息方面表现不佳,则可能无法识别该索引会产生完全碎片化的磁盘读取。这可能是您遇到的情况。

尝试分析表格以收集新的统计数据:

http://dev.mysql.com/doc/refman/5.5/en/analyze-table.html

然后使用和不使用索引重试。