2010-11-15 72 views
1

我需要一些帮助优化MySQL查询或表MySQL的加入时间太长

当我运行此查询它.01s 650次返回的记录:

select mm, name, display, year 
    from tbl d 
    where active = 1 and tbl2_id = 'val' and lvl_id = 9 
    order by mm; 

当我运行此查询它长达15秒返回与相同的记录:

select d.mm, d.name, d.display, d.year, a.year year2 
    from tbl d left join tbl a on d.mm = a.mm and a.tbl2_id = 'val2' 
    where d.active = 1 and d.tbl2_id = 'val' and d.lvl_id = 9 
    order by d.mm; 

当我运行它,这样它也需要长达15秒:

select mm, name, display, year, 
     (select a.year from tbl a where a.mm = mm and a.tbl2_id = 'val2') year2 
    from tbl 
    where active = 1 and tbl2_id = 'val' and lvl_id = 9 
    order by mm; 

表中有多个mm记录。我需要得到tbl2_id ='val'的所有记录,并且如果有这样的记录,那么tbl2_id ='val2'时,我需要val2记录中的“年份”值。 tbl目前有13k条记录,并且没有超过10条记录,所以我不认为这个查询应该超过15秒。我有索引mm,active,tbl2_id和lvl_id。

我已经做过类似的事情在MSSQL,几乎没有延迟。

+2

你可以在你的查询上运行'EXPLAIN'并发布查询计划吗? http://dev.mysql.com/doc/refman/5.0/en/explain.html – thomaspaulb 2010-11-15 22:23:45

回答

3

您可以通过在(tbl2_id,lvl_id,有源)和(tbl2_id,毫米)你的桌子上引入复合索引开始。这可能会加快你的三个疑问。

每当在WHERE子句中使用多个字段,这是有道理考虑一个综合指数。在情况下,只有单个列索引存在,查询可以仅使用这些索引中的一个为一个而不必诉诸较慢扫描搜索剩余的子集寻求。 MySQL和MSSQL在这方面的区别可能在于,MSSQL根据数据的基数(最好使用的是离开扫描的最小子集的数据)来更好地猜测这三者中哪一个可以使用,尽管如果没有详细检查两个查询计划,这很难说。

+0

对不起,它应该是a.mm = mm。我会解决它。 – 2010-11-15 22:34:27

+0

好的,在这种情况下,索引建议对所有三个查询都有效。答案已更新。 – thomaspaulb 2010-11-15 22:40:45

+0

快速的网页搜索“复合索引mysql”后,我能够创建一个新的索引(mm,tbl2_id,lvl_id,动作),这有助于显着。现在,连接与我的第一个查询运行大致相同。 – 2010-11-15 22:49:58

1

索引连接条件(mm)中使用的列应该有所帮助。

+0

这个问题表明这样一个索引已经存在。 – 2010-11-15 22:26:18

2

你能提供的表的DESCRIBE和查询的EXPLAIN

使用字符串查找INT字段或整数以查找CHAR/VARCHAR字段存在已知问题。基本上INDEX被忽略。

如果lvl_idactiveCHAR/VARCHAR这可能是原因。如果这种类型为INT,则tbl2_id也是如此。

编辑

我必须说,13K条目是没有什么可以解释的性能。但是,您应该考虑索引的基数。如果基数低于30%(等因素),您的指数将不会被使用。

使用EXPLAIN当问如何查询优化器做了查询,并利用它什么索引这应该是清楚的。在某些情况下,您可能希望使用FORCE INDEX语法明确使用一个或多个索引。

另外请记住,虽然添加复合索引有助于提高查询速度(通过增加索引的基数并因此使查询优化器自动使用它),但它也会有不利之处。更多索引意味着更多的空间使用和减速UPDATE/INSERT因为更多的东西需要更新。如果表格变得相当大(在数百万行的范围内),这尤其相关。