Mysql查询优化、解释和缓慢执行
在一些问题上有一些实际问题,特别是这个问题。信息如下 tgmp_游戏,约2万行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
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 您还可以尝试对每个表运行分析来更新统计信息,以查看优化器是否选择了不同的内容
分组的目的是什么,但这会使MySQL对所选列或两个表中的所有列执行聚合。因此,请尝试排除它,并检查它是否有帮助
RIGHT JOIN
首先让数据库查询tgmp\u评论
,这不是您想要的。我想左连接在这里是一个更好的选择。请尝试更改联接类型
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;