3

对一些查询有一些实际问题,尤其是这个。信息如下。

tgmp_games,大约 20k 行

CREATE TABLE IF NOT EXISTS `tgmp_games` (
  `g_id` int(8) NOT NULL AUTO_INCREMENT,
  `site_id` int(6) NOT NULL,
  `g_name` varchar(255) NOT NULL,
  `g_link` varchar(255) NOT NULL,
  `g_url` varchar(255) NOT NULL,
  `g_platforms` varchar(128) NOT NULL,
  `g_added` datetime NOT NULL,
  `g_cover` varchar(255) NOT NULL,
  `g_impressions` int(8) NOT NULL,
  PRIMARY KEY (`g_id`),
  KEY `g_platforms` (`g_platforms`),
  KEY `site_id` (`site_id`),
  KEY `g_link` (`g_link`),
  KEY `g_release` (`g_release`),
  KEY `g_genre` (`g_genre`),
  KEY `g_name` (`g_name`),
  KEY `g_impressions` (`g_impressions`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

tgmp_reviews - 大约 200k 行

CREATE TABLE IF NOT EXISTS `tgmp_reviews` (
  `r_id` int(8) NOT NULL AUTO_INCREMENT,
  `site_id` int(6) NOT NULL,
  `r_source` varchar(128) NOT NULL,
  `r_date` date NOT NULL,
  `r_score` int(3) NOT NULL,
  `r_copy` text NOT NULL,
  `r_link` text NOT NULL,
  `r_int_link` text NOT NULL,
  `r_parent` int(8) NOT NULL,
  `r_platform` varchar(12) NOT NULL,
  `r_impressions` int(8) NOT NULL,
  PRIMARY KEY (`r_id`),
  KEY `site_id` (`site_id`),
  KEY `r_parent` (`r_parent`),
  KEY `r_platform` (`r_platform`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 ;

这是查询,需要 3 秒 ish

SELECT * FROM tgmp_games g
RIGHT JOIN tgmp_reviews r ON g_id = r.r_parent
WHERE g.site_id = '34'
GROUP BY g_name
ORDER BY g_impressions DESC LIMIT 15

解释

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  r   ALL     r_parent    NULL    NULL    NULL    201133  Using temporary; Using filesort
1   SIMPLE  g   eq_ref  PRIMARY,site_id     PRIMARY     4   engine_comp.r.r_parent  1   Using where

我只是想获取观看次数最多的 15 款游戏,然后为每款游戏获取一条评论(这并不重要,我想最高评分是理想的,r_score)。

有人可以帮我弄清楚为什么这效率如此之低吗?

4

2 回答 2

2
  1. 我不明白GROUP BY g_name在您的查询中使用 a 的目的是什么,但这会使 MySQL 对所选列或两个表中的所有列执行聚合。所以请尝试排除它并检查它是否有帮助。

  2. 另外,RIGHT JOIN让数据库先查询tgmp_reviews,这不是你想要的。我想LEFT JOIN这里是一个更好的选择。请尝试更改连接类型。

  3. 如果第一个选项都没有帮助,您需要重新设计查询。由于您需要为该站点获取 15 个观看次数最多的游戏,因此查询将是:

    SELECT g_id
      FROM tgmp_games g
     WHERE site_id = 34
     ORDER BY g_impressions DESC
     LIMIT 15;
    

    这是应该由数据库执行的第一部分,因为它提供了最好的选择性。然后,您可以获得所需的游戏评论:

    SELECT r_parent, max(r_score)
      FROM tgmp_reviews r
     WHERE r_parent IN (/*1st query*/)
     GROUP BY r_parent;
    

    这样的构造将强制数据库首先执行第一个查询(对不起重言式),并且会给你每个想要的游戏的最高分数。我希望您能够将获得的结果用于您的目的。

于 2012-08-09T20:04:45.947 回答
1

您的 MyISAM 表很小,您可以尝试转换它以查看是否可以解决问题。您是否有理由为该表使用 MyISAM 而不是 InnoDB?

您还可以尝试对每个表运行分析以更新统计信息,以查看优化器是否选择了不同的东西。

于 2012-08-09T17:15:32.157 回答