使用带有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 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
有人可以帮我解释一下为什么这个索引在逻辑上似乎不应该减慢这么多的东西吗?
答案 0 :(得分:2)
当您的数据库引擎决定读取索引时,它会按顺序逐个读取行。这可以使它读取磁盘页面2中的一行,第4页中的另一行,第1页中的另一行,第2页中的下一行等。
有时,反复来回是指数没有帮助 - 恰恰相反。
如果数据库引擎在生成查询计划时收集和分析表上的统计信息方面表现不佳,则可能无法识别该索引会产生完全碎片化的磁盘读取。这可能是您遇到的情况。
尝试分析表格以收集新的统计数据:
http://dev.mysql.com/doc/refman/5.5/en/analyze-table.html
然后使用和不使用索引重试。