Mysql查询优化、解释和缓慢执行

Mysql查询优化、解释和缓慢执行,mysql,optimization,query-optimization,explain,Mysql,Optimization,Query Optimization,Explain,在一些问题上有一些实际问题,特别是这个问题。信息如下 tgmp_游戏,约2万行 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 NUL

在一些问题上有一些实际问题,特别是这个问题。信息如下

tgmp_游戏,约2万行

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_审查-约20万行

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秒钟

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_分数并不重要)


有人能帮我找出为什么效率如此之低吗?

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

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

  • 我不明白在查询中按g_name创建
    分组的目的是什么,但这会使MySQL对所选列或两个表中的所有列执行聚合。因此,请尝试排除它,并检查它是否有帮助

  • 另外,
    RIGHT JOIN
    首先让数据库查询
    tgmp\u评论
    ,这不是您想要的。我想
    左连接
    在这里是一个更好的选择。请尝试更改联接类型

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

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

    SELECT r_parent, max(r_score)
      FROM tgmp_reviews r
     WHERE r_parent IN (/*1st query*/)
     GROUP BY r_parent;
    
    这种构造将迫使数据库首先执行第一个查询(抱歉重言式),并为每个想要的游戏提供最大分数。我希望您能够将获得的结果用于您的目的


  • WHERE g.site\u id='34'
    条件使查询相当于一个
    内部
    联接。@ypercube您能解释为什么吗?外部联接选择所有联接的数据,加上(在右联接的情况下)右侧的所有数据,
    r
    此处,与左侧的任何行都不匹配,
    g
    此处。然后这些额外的行在这里被拒绝,因为
    g.site_id
    为空(当然不等于34)。请记住,这些行在
    g
    表中没有匹配项。无论如何,
    右连接在这里没有意义。我想你永远不会有一个不涉及游戏的评论。是吗?我需要全文索引:(将给分析人员一个尝试性的答案:)1。分组是因为每场游戏有多个评论,而我只希望每场游戏有一个评论。2.LEFT JOIN可以选择没有评论的游戏实例,这是我不想要的,并添加和r_分数!=''似乎不起作用。3.起初,我有来自as的评论并参加了比赛,但那同样糟糕。我会尝试一下这个解决方案,但是在这么大的桌子上运行会不会也相当低效呢?我现在就试试,谢谢!我需要的不仅仅是游戏中的g_id,而且我的mysql版本不允许在子查询中进行限制。因此,我们必须将其作为两个单独的查询,并在第二个查询中使用PHP构建。此外,我还需要正确的连接来只返回带有评论的游戏,但我还是通过提高游戏查询的限制,并使用PHP来限制它并丢弃我不需要的结果,从而绕过了这个问题。感谢您的帮助,这两个查询组合运行时间<0.02秒,更好:)@Horse,如果您需要具有评论的游戏,请使用
    内部连接
    ,它更适合并执行得更快。另外,不要使用PHP来组合两个查询的结果,而是考虑其他解决方案,比如使用视图或存储过程。您的MySQL在子查询中不支持
    LIMIT
    ,这一事实似乎非常有限:)
    SELECT r_parent, max(r_score)
      FROM tgmp_reviews r
     WHERE r_parent IN (/*1st query*/)
     GROUP BY r_parent;