使用多个左连接优化MySQL查询

时间:2011-10-12 05:34:45

标签: mysql sql optimization

我有一个NewsStories表,我还要加入一些相关的表。每个新闻故事可以有多个图像,类别和地址。所以查询基本上是:

SELECT * FROM NewStories 

LEFT JOIN Images ON Newstories.id=Images.story_id

LEFT JOIN Categories ON NewsStories.id=Categories.story_id

LEFT JOIN Addresses ON NewsStories.id=Addresses.story_id

WHERE ...

每个故事通常有一些图像和地址,以及1或2个类别。 NewsStories表有大约10,000篇文章。

麻烦的是性能相当慢(大约15-20秒,虽然它确实变化很大,有时会下降到5秒)。

我想知道是否有更好的方法来组织查询以加快速度(我对SQL很新)。

特别是,给定故事的行数乘以图像数乘以地址数乘以类别数量似乎相当浪费。

我基本上试图将新闻故事的属性重建为一个我可以在前端操作的对象。

这是解释(如果格式化不正确,请道歉)。我猜我没有正确索引地址,如果它是“使用在哪里”。这是对的吗?

id  select_type table   type    possible_keys   key key_len ref rows    Extra

1   SIMPLE  Addresses   ALL NULL    NULL    NULL    NULL    6640    Using where

1   SIMPLE  NewsStories eq_ref  PRIMARY PRIMARY 767 NewsStories.Addresses.story_id 1    Using where

1   SIMPLE  Images  ref PRIMARY PRIMARY 767 NewsStories.NewsStories.id  1   Using index

1   SIMPLE  Categories  ref PRIMARY PRIMARY 767 NewsStories.NewStories.id   1

2 个答案:

答案 0 :(得分:7)

  • 确保在WHERE语句和ON条件中的字段上有索引,默认情况下会对主键建立索引,但如果必须,还可以手动创建索引。
  

CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name       [INDEX_TYPE]       ON tbl_name(index_col_name,...)       [INDEX_TYPE]

     

一个index_col_name:       col_name [(长度)] [ASC | DESC]

     

INDEX_TYPE:       使用{BTREE | HASH}

  • 检查是否真的必须选择所有表中的每一列?如果没有,请确保您只选择所需的列,避免使用选择*

  • 仔细检查你是否真的需要LEFT JOINS,如果不是,请使用INNER JOIN。

  • 如果在完成调整查询后性能仍然存在问题,请考虑对模式进行非规范化以消除连接

  • 您可能还想考虑使用sphinxsearch和memcached等缓存应用程序来减少数据库的负载

  • 检查您的联接都不是视图而不是实际的表

的引用:

http://www.sphinxsearch.com

http://dev.mysql.com/doc/refman/5.0/en/create-index.html

答案 1 :(得分:0)

确保您的表格已正确编入索引。您需要为每个用于选择数据的列创建索引,否则MySQL将遍历表中的每一行。

尝试在MySQL控制台中解释查询(EXPLAIN SELECT * FROM ...etc),以了解MySQL如何在内部处理表格。将结果粘贴到您的问题中以获得其他帮助。