当 B 与 A 匹配时,在表 A 上左连接表 B 是瞬时的,但在没有匹配时需要永远(> 1 分钟)。为啥是这样?
Posted
技术标签:
【中文标题】当 B 与 A 匹配时,在表 A 上左连接表 B 是瞬时的,但在没有匹配时需要永远(> 1 分钟)。为啥是这样?【英文标题】:Left Joining table B on table A is instantaneous when B has matches to A, but takes forever (> 1 minute) when there are no matches. Why is this?当 B 与 A 匹配时,在表 A 上左连接表 B 是瞬时的,但在没有匹配时需要永远(> 1 分钟)。为什么是这样? 【发布时间】:2020-08-06 18:46:06 【问题描述】:我想:
SELECT T.TournamentId, Sum(Score) as Score
FROM Tournament T
LEFT JOIN Scores S on S.TournamentId = T.TournamentId
WHERE T.TournamentId = x
GROUP BY T.TournamentId
当我在尚未开始的 WHERE 子句中选择 TounamentId "x" 时,查询需要永远运行。当我为已开始的锦标赛选择“x”时,它会立即运行。
真正的查询比这复杂一点。但这是问题的根源。为什么会这样,我该怎么做才能加快速度?我希望能够对这两种情况使用相同的查询。但如果我无能为力,我将创建第二个查询,以便在锦标赛尚未开始时运行。
【问题讨论】:
您在表 Scores 中是否有按 TournamentId 字段的索引? 【参考方案1】:如果任何一个表非常大,这个问题是有道理的,在这种情况下,你应该尽可能地限制它(有些人会声称服务器会自己做,但并非所有的情况都是如此。时间)。
试一试
SELECT
T.TournamentId, SUM(Score) AS Score
FROM
Tournament T
LEFT JOIN
Scores S ON S.TournamentId = T.TournamentId AND S.TournamentId = x
WHERE
T.TournamentId = x
GROUP BY
T.TournamentId
否则,您可以编写一个存储过程并创建一个临时表,该表是 S 的副本,但仅包含 TournamentId = x 的行。连接对数据库来说总是很繁重,在连接中使用它们之前缩小表可以加快数百万百分比的速度。
正如所指出的,您还可以使用索引来加快速度,在这种情况下,索引需要在您加入的值上,您还应该考虑定期重建索引(在 mssql 中很容易,在 mysql 中很痛苦)。 为了加快速度,您可以向临时表添加自定义索引,特别是如果您有许多巨大的表,这将使事情变得更快,如果它只是几百/千行的影响将可以忽略不计甚至是负面的..
# Make sure the tables are not already there
DROP TEMPORARY TABLE IF EXISTS tmp_Tournament;
DROP TEMPORARY TABLE IF EXISTS tmp_Scores;
CREATE TEMPORARY TABLE tmp_Tournament
SELECT * from Tournament WHERE TournamentId = x;
CREATE INDEX tmp_Tournament_TournamentId ON tmp_Tournament (TournamentId);
CREATE TEMPORARY TABLE tmp_Scores
SELECT * FROM Scores WHERE TournamentId = x;
CREATE INDEX tmp_Scores_TournamentId ON tmp_Scores (TournamentId);
SELECT
T.TournamentId, SUM(Score) AS Score
FROM
tmp_Tournament T
LEFT JOIN
tmp_Scores S ON S.TournamentId = T.TournamentId AND S.TournamentId = x
WHERE
T.TournamentId = x
GROUP BY
T.TournamentId;
# Just some cleanup
DROP TEMPORARY TABLE IF EXISTS tmp_Tournament;
DROP TEMPORARY TABLE IF EXISTS tmp_Scores;
【讨论】:
临时表的想法拯救了一天!查询现在以闪电般的速度运行。谢谢你的建议! 您还可以索引列以提高查询速度/性能 - 请参阅讨论:***.com/questions/52988287/…以上是关于当 B 与 A 匹配时,在表 A 上左连接表 B 是瞬时的,但在没有匹配时需要永远(> 1 分钟)。为啥是这样?的主要内容,如果未能解决你的问题,请参考以下文章