【发布时间】:2014-11-04 00:03:51
【问题描述】:
我有一个包含以下三个表的数据库:
matches 表有 200,000 个匹配项...
CREATE TABLE `matches` (
`match_id` bigint(20) unsigned NOT NULL,
`start_time` int(10) unsigned NOT NULL,
PRIMARY KEY (`match_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
英雄表有大约 100 个英雄...
CREATE TABLE `heroes` (
`hero_id` smallint(5) unsigned NOT NULL,
`name` char(40) NOT NULL,
PRIMARY KEY (`hero_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
matches_heroes 表有 2,000,000 个关系(每场比赛 10 个随机英雄)...
CREATE TABLE `matches_heroes` (
`relation_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`match_id` bigint(20) unsigned NOT NULL,
`hero_id` smallint(6) unsigned NOT NULL,
PRIMARY KEY (`relation_id`),
KEY `match_id` (`match_id`),
KEY `hero_id` (`hero_id`),
CONSTRAINT `matches_heroes_ibfk_2` FOREIGN KEY (`hero_id`)
REFERENCES `heroes` (`hero_id`),
CONSTRAINT `matches_heroes_ibfk_1` FOREIGN KEY (`match_id`)
REFERENCES `matches` (`match_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3689891 DEFAULT CHARSET=utf8
以下查询需要 1 秒以上,对于这么简单的事情,这对我来说似乎很慢:
SELECT SQL_NO_CACHE COUNT(*) AS match_count
FROM matches INNER JOIN matches_heroes ON matches.match_id = matches_heroes.match_id
WHERE hero_id = 5
仅删除 WHERE 子句没有帮助,但如果我也取出 INNER JOIN,如下所示:
SELECT SQL_NO_CACHE COUNT(*) AS match_count FROM matches
...只需要 0.05 秒。看来 INNER JOIN 的成本很高。我没有太多的连接经验。这是正常的还是我做错了什么?
更新 #1:这是 EXPLAIN 结果。
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE matches_heroes ref match_id,hero_id,match_id_hero_id hero_id 2 const 34742
1 SIMPLE matches eq_ref PRIMARY PRIMARY 8 mydatabase.matches_heroes.match_id 1 Using index
更新#2:听了你们的意见后,我认为它工作正常,而且速度很快。如果您不同意,请告诉我。感谢所有的帮助。我真的很感激。
【问题讨论】:
-
你有 hero_id 的索引吗? EXPLAIN() 告诉您关于该查询的什么信息?
-
看起来
hero_id = 5需要进行表扫描。也许您可以在该字段上添加索引。 -
您在字段
matches_heroes.hero_id和matches_heroes.match_id上有没有索引的外键。我建议您将索引添加到matches_heroes.hero_id并重复查询。 -
@Andomar, @Cornelius, @user1516873 我看过他的执行计划,他在那里有钥匙:sqlfiddle.com/#!2/14a8ba/1
KEY match_id (match_id), KEY hero_id (hero_id),在Create table, key is an alias for index -
@clickstefan:你是对的