在一些查询中遇到一些实际问题,特别是这个问题。信息如下。
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
EXPLAIN
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)。
有人可以帮我弄清楚为什么这种效率非常低效吗?
答案 0 :(得分:2)
我不明白在查询中使用GROUP BY g_name
的目的是什么,但这会使MySQL在所选列上执行聚合,或者在两个表中执行所有列。所以请尽量排除它并检查它是否有帮助。
此外,RIGHT JOIN
使数据库首先查询tgmp_reviews
,这不是您想要的。我想LEFT JOIN
在这里是更好的选择。请尝试更改连接类型。
如果第一个选项都没有帮助,则需要重新设计查询。由于您需要为该网站获得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;
这样的构造将强制数据库首先执行第一个查询(对于重言式抱歉)并且将为每个想要的游戏提供最大分数。我希望您能够将获得的结果用于您的目的。
答案 1 :(得分:1)
您的MyISAM表很小,您可以尝试转换它以查看是否可以解决问题。你是否有理由在该表中使用MyISAM而不是InnoDB?
您还可以尝试在每个表上运行分析以更新统计信息,以查看优化程序是否选择了不同的内容。