MySQL查询非常慢

时间:2013-04-10 08:35:18

标签: mysql innodb optimization

您好我正在寻找优化mysql查询的方法,基本上我正在为属于category_id = 25的用户提取文章而source_id不在我存储来自用户取消订阅的源ID的表中。

select
  a.article_id,
  a.article_title,
  a.source_id,
  a.article_publish_date,
  a.article_details,
  n.source_name
from sources n
  INNER JOIN articles a
    ON (a.source_id = n.source_id)
WHERE n.category_id = 25
    AND n.source_id NOT IN(select
                 source_id
               from news_sources_deselected
               WHERE user_id = 5)
ORDER BY a.article_publish_date DESC

文章表格架构

CREATE TABLE IF NOT EXISTS `articles` (<br>
  `article_id` int(255) NOT NULL auto_increment,<br>
  `article_title` varchar(255) NOT NULL,<br>
  `source_id` int(255) NOT NULL,<br>
  `article_publish_date` bigint(255) NOT NULL,<br>
  `article_details` text NOT NULL,<br>
  PRIMARY KEY  (`article_id`),<br>
  KEY `source_id` (`source_id`),<br>
  KEY `article_publish_date` (`article_publish_date`)<br>
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='Contains articles.';

来源表的结构

CREATE TABLE IF NOT EXISTS `sources` (<br>
  `source_id` int(255) NOT NULL auto_increment,<br>
  `category_id` int(255) NOT NULL,<br>
  `source_name` varchar(255) character set latin1 NOT NULL,<br>
  `user_id` int(255) NOT NULL,<br>
  PRIMARY KEY  (`source_id`),<br>
  KEY `category_id` (`category_id`),<br>
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='News Sources.'

文章表有大约30万条记录,而源表包含大约1000条记录,查询大约需要180秒才能执行。

非常感谢任何帮助。

enter image description here

5 个答案:

答案 0 :(得分:1)

尝试使用IS NULL条件的derieved查询。你解释说有一个依赖子查询。忽略使用它并使用derieved查询您的问题。这将提高性能

select
  a.article_id,
  a.article_title,
  a.source_id,
  a.article_publish_date,
  a.article_details,
  n.source_name
from sources n
  INNER JOIN articles a
    ON (a.source_id = n.source_id)
  LEFT JOIN (SELECT *
         FROM news_sources_deselected
         WHERE user_id = 5) AS nsd
    ON nsd.source_id = n.source_id
WHERE n.category_id = 25
    AND nsd.source_id IS NULL
ORDER BY a.article_publish_date DESC

答案 1 :(得分:0)

在查询前使用EXPLAIN并分析结果。

Here您可以找到如何开始优化工作。

答案 2 :(得分:0)

我看到你可以检查的问题很少。

  • 尽管使用了InnoDB引擎,但你并没有使用关系。
  • 您正在选择没有索引的字段。
  • 您一次选择所有行。

您是否需要同时使用所有这些行?也许考虑将此查询拆分为多个分片(分页)?

答案 3 :(得分:0)

尝试此查询

select
 a.article_id,
 a.article_title,
 a.source_id,
 a.article_publish_date,
 a.article_details,
 n.source_name
from 
 sources n
INNER JOIN 
 articles a
ON 
 n.category_id = 25 AND 
 a.source_id = n.source_id     
INNER JOIN 
 news_sources_deselected nsd
ON
 nsd.user_id <> 5 AND n.source_id = nsd.source_id
ORDER BY 
 a.article_publish_date DESC

我已删除了额外的查询,并在加入时添加了news_sources_deselected,接受除了source_id以外的user_id的所有5

或者我们可以按照用户raheelshan提到的那样仅使用所需的连接记录

select
 a.article_id,
 a.article_title,
 a.source_id,
 a.article_publish_date,
 a.article_details,
 n.source_name
from 
 (select 
   * 
 from 
   sources 
 where 
   category_id = 25) n 
INNER JOIN 
 articles a
ON 
 a.source_id = n.source_id     
INNER JOIN 
 (select 
   * 
 from 
   news_sources_deselected 
 where 
   user_id <> 5) nsd
ON
 n.source_id = nsd.source_id
ORDER BY 
 a.article_publish_date DESC

希望这会有所帮助..

答案 4 :(得分:0)

我通过对表格进行分区来解决问题,但我仍然愿意接受建议。