【发布时间】:2014-03-19 23:52:06
【问题描述】:
我有 2 个组,我试图找到它们的交集(需要 2 个列来匹配),并且我发现加入 2 个临时表会产生比仅加入一个原始表慢 50 倍的性能临时表。这对我来说毫无意义,所以也许有人可以启发我?
这是我编写 2 个临时表版本的方式:
CREATE TEMPORARY TABLE attendees (
event_id SMALLINT(5) UNSIGNED,
person_id INT(10) UNSIGNED NOT NULL,
KEY(event_id),
KEY(person_id)
);
INSERT INTO attendees (event_id, person_id)
SELECT event_id, person_id
FROM attendance WHERE year=2013
GROUP BY event_id, person_id;
CREATE TEMPORARY TABLE invitees (
event_id SMALLINT(5) UNSIGNED,
person_id INT(10) UNSIGNED NOT NULL,
KEY(event_id),
KEY(person_id)
);
INSERT INTO invitees (event_id, person_id)
SELECT event_id, person_id
FROM invitations WHERE year=2013
GROUP BY event_id, person_id;
SELECT i.event_id, COUNT(DISTINCT i.person_id)
FROM attendees AS a
INNER JOIN invitees AS i
ON a.person_id = i.person_id AND a.event_id = i.event_id
GROUP BY i.event_id;
这 2 个临时表中的每一个都少于 2,000 行,但在我的笔记本电脑上,这个最终查询大约需要 2.5 秒。我不明白这怎么可能。
另一方面,通过以下实现,最终查询只需要 0.05 秒,即使它正在访问完整的邀请表(约 100,000 行):
CREATE TEMPORARY TABLE attendees (
event_id SMALLINT(5) UNSIGNED,
person_id INT(10) UNSIGNED NOT NULL,
KEY(event_id),
KEY(person_id)
);
INSERT INTO attendees (event_id, person_id)
SELECT event_id, person_id
FROM attendance WHERE year=2013
GROUP BY event_id, person_id;
SELECT i.event_id, COUNT(DISTINCT i.person_id)
FROM attendees AS a
INNER JOIN invitations AS i
ON a.person_id = i.person_id AND a.event_id = i.event_id
WHERE i.year=2013
GROUP BY i.event_id;
不管怎样,原始表(出席和邀请)都有关于 event_id、person_id 和 year 的索引。而我首先编写如此复杂的代码的原因是,有些活动的参与者没有被邀请,我必须计算这些人的维恩图每个部分的计数(参加和邀请,未受邀参加,受邀未参加,均未参加)。
我想我的问题是,这里发生了什么让第二个版本变得如此之快?
以防万一,我的服务器版本是 5.5.36 MySQL Community Server(5.6 有几个奇怪的行为破坏了我的网站)。
【问题讨论】:
-
为什么要搞乱临时表方法?
-
@MikeBrant 我敢打赌他认为使用较小的桌子会更快:)
-
如果您有一个更好的建议,它将生成一个事件列表,其中包含 (1) 受邀参加者、(2) 未受邀参加者和 (3) 未受邀参加者的数量不参加,我很想看看。在我在这里引用的查询之后,我对这些表进行了更多查询,它们只是没有任何性能问题。
标签: mysql join inner-join temp-tables