MySQL Join花了太长时间

时间:2010-11-15 22:18:29

标签: mysql query-optimization

我需要一些优化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'的所有记录,如果有mm的记录,其中tbl2_id ='val2',我需要val2记录中的“year”值。 tbl目前有13k记录,任何给定的mm都不超过10条记录,所以我认为这个查询不应该超过15秒。我有索引mm,active,tbl2_id和lvl_id。

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

3 个答案:

答案 0 :(得分:3)

您可以首先在表上引入复合索引(tbl2_id,lvl_id,active)和(tbl2_id,mm)。这可能会加快你的所有三个查询。

每当在WHERE子句中使用多个字段时,考虑复合索引是有意义的。如果仅存在单列索引,则查询只能使用其中一个索引进行搜索,而不得不求助于较慢的扫描来搜索剩余的子集。在这方面,MySQL和MSSQL之间的区别可能是MSSQL根据数据的基数更好地猜测这三者中哪一个使用(最好的一个将是留下扫描的最小子集的那个),虽然如果不详细检查两个查询计划就很难说。

答案 1 :(得分:2)

您能提供DESCRIBE个表格以及查询的EXPLAIN吗?

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

如果lvl_idactiveCHAR / VARCHAR,则可能是原因。如果tbl2_id类型为INT,则同样有效。

修改

我必须说13k条目不能解释性能。但是,您应该考虑索引的基数。如果基数低于30%(除其他因素外),您的指数将不会被使用。

使用EXPLAIN询问查询优化器如何执行查询以及它使用的是哪些索引时,应该清楚这一点。在某些情况下,您可能希望使用FORCE INDEX语法显式使用一个或多个索引。

另外请记住,添加复合索引有助于提高查询速度(通过增加索引的基数,从而使查询优化器自动使用它),它也会有缺点。由于需要更新更多内容,因此更多索引意味着使用更多空间并降低UPDATE / INSERT的速度。如果您的表变得非常大(在数百万行的范围内),这是特别相关的。

答案 2 :(得分:1)

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