第一次查询耗时超过5秒


First query take more then 5 seconds

所以我有这个查询

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

我试着用join来做,但根本不起作用,所以我放弃了这种方式。。。

解决方案

使用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:)

改为尝试此查询:

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上有索引。

我想,第二次尝试是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;

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

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

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

但您肯定应该尝试在关闭缓存的情况下优化查询的性能——5秒非常慢。

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