第一次查询需要5秒以上

时间:2013-12-15 07:47:17

标签: php mysql

所以我有这个查询

SELECT a.`title`,a.`id`,a.`numvol`,a.`numepi`,a.`release_date`,
     (SELECT COUNT(id) FROM `Release` r WHERE r.`article_id`=a.`id`) AS `num_rows`,
     (SELECT COUNT(id) FROM `Article_views` av WHERE av.`article_id`=a.`id`) AS `num_rows2`
 FROM `Article` a  WHERE a.`type` = 'ani' ORDER BY a.`title` ASC

第一次加载需要5秒钟,如果我刷新它需要大约0.001秒,有没有办法统一加载时间?

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY             a   ALL     NULL            NULL    NULL        NULL    567     Using where; Using filesort
3   DEPENDENT SUBQUERY  av  ALL     NULL            NULL    NULL        NULL    5301    Using where
2   DEPENDENT SUBQUERY  r   ALL     NULL            NULL    NULL        NULL    11717   Using where

我试图通过加入来做,但它根本不起作用,所以我放弃了这种方式......

解决方案

使用barmar查询。方式更好:)(和索引 - , - ')

id  select_type     table          type     possible_keys   key         key_len     ref     rows    Extra
1   PRIMARY         <derived2>     ALL      NULL            NULL        NULL        NULL    536     Using temporary; Using filesort
1   PRIMARY         a              eq_ref   PRIMARY         PRIMARY     4           r.art.. 1       Using where  
1   PRIMARY         <derived3>     ALL      NULL            NULL        NULL        NULL    574     Using where; Using join buffer
3   DERIVED         Article_views  index    NULL            article_id  4           NULL    5301    Using index
2   DERIVED         Release        index    NULL            article_id  4           NULL    11717   Using index

谢谢你们的时间和解决方案:)我想我需要重做这个旧项目的一个很好的部分ahah:)

3 个答案:

答案 0 :(得分:4)

请尝试此查询:

SELECT a.`title`,a.`id`,a.`numvol`,a.`numepi`,a.`release_date`, `num_rows`, `num_rows2`
FROM `Article` a
JOIN (SELECT article_id, COUNT(*) AS num_rows
      FROM Release
      GROUP BY article_id) r
ON r.article_id = a.id
JOIN (SELECT article_id, COUNT(*) AS num_rows2
      FROM Article_views
      GROUP BY article_id) av
ON av.article_id = a.id
WHERE a.`type` = 'ani'
ORDER BY a.`title` ASC

根据我的经验,JOIN比相关子查询更快。

为了提高性能,请确保您在Release.article_idArticle_views.article_id上有索引。

答案 1 :(得分:2)

我猜,第二次尝试是受益于SQL QUERY CACHE。我想知道是否添加SQL_NO_CACHE,每次尝试都需要5秒钟?

SELECT SQL_NO_CACHE a.`title`,a.`id`,a.`numvol`,a.`numepi`,a.`release_date`,
....

<强>指标

糟糕。你没有相关的INDEX。你可以添加以下索引吗?

ALTER TABLE Article ADD INDEX(type);
ALTER TABLE Release ADD INDEX(article_id);
ALTER TABLE Article_views ADD INDEX(article_id);

更有效的查询

您的查询已转换为JOIN。我想这比你的快得多。假设每个Article都有ReleaseArticle_views

SELECT a.`title`,a.`id`,a.`numvol`,a.`numepi`,a.`release_date`,
     COUNT(r.id) AS `num_rows`,
     COUNT(av.id) AS `num_rows2`
FROM `Article` a JOIN Release r ON r.`article_id`=a.`id`
  JOIN Article_views av ON av.`article_id`=a.`id`
WHERE a.`type` = 'ani'
GROUP BY a.title, a.id, a.numvol, a.numepi, a.release_date
ORDER BY a.`title` ASC;

答案 2 :(得分:1)

查询延迟的显着改进是由于内部MySQL缓存功能。

在第一次执行查询后,结果集被缓存在RAM中,因此结果第二个查询与之前的查询匹配,立即从RAM中获取而不进行HDD访问。

关于MySQL内部缓存有不同的观点,专家经常建议使用memecached,Redis或其他一些缓存层在高负载生产环境中禁用它。

但绝对应该尝试在关闭缓存的情况下优化查询的性能 - 5秒非常慢。

  1. 尽量不要使用子查询,因为MySQL优化器不具备它们的性能。
  2. 将计数器的值(count()的结果)存储在单独的表中并正确更新它们。然后,您可以在查询中仅使用计数器值,而无需每次都执行大量数据库请求。
  3. 例如,为type字段创建索引。
  4. 使用EXPLAIN进行进一步优化