gpt4 book ai didi

mysql - 在指定了 ORDER BY 和 LIMIT 并且实际上只需要连接少量行的 JOIN 情况下,MySQL 的行为如何?

转载 作者:行者123 更新时间:2023-11-29 02:37:10 30 4
gpt4 key购买 nike

假设我有以下表格:

CREATE TABLE Game (
GameID INT UNSIGNED NOT NULL,
GameType TINYINT UNSIGNED NOT NULL,
PRIMARY KEY (GameID),
INDEX Index_GameType (GameType, GameID)
) ENGINE=INNODB

CREATE TABLE HighScore (
Game INT UNSIGNED NOT NULL,
Score SMALLINT UNSIGNED,
PRIMARY KEY (Game),
INDEX Index_Score (Score, Game),
CONSTRAINT Constr_Score_Game_fk
FOREIGN KEY Score_Game_fk (Game) REFERENCES Game (GameID)
) ENGINE=INNODB

(这些是我正在使用的真实表的精简版。真实表有更多的列和索引。上面的表捕捉了这种情况的基本特征。)

(应该假设不同GameType的数量很少,所以索引Index_GameType不是很有选择性。)

假设我运行以下查询:

SELECT
HighScore.Score
FROM
HighScore
JOIN Game ON HighScore.Game = Game.GameID
WHERE
Game.GameType = 42
ORDER BY
HighScore.Score DESC
LIMIT 50

查看此查询和表设计,我们可能会同意,明智的做法是向下扫描 HighScore 表并连接行,直到找到 50 个满足 WHERE 条件的行。然而,对我来说,一个 EXPLAIN 显示(使用我真实的、更复杂的表)MySQL 实际上计划在 Game 中查找满足 WHERE 条件的所有行,将其与 HighScore 连接,并执行文件排序以按排序顺序获取行。

因此在上述查询中指定 STRAIGHT_JOIN 似乎是明智的。现在 EXPLAIN 输出表明第一个表 HighScore 正在“使用索引”(正如预期的那样),但报告的行数似乎是 HighScore 表中的行数。我是否应该认为这意味着 MySQL 计划基本上获取整个索引,将该索引中的每一行连接到另一个表,然后才丢弃前 50 名以下的行?这看起来很荒谬,但我不确定这是否真的会这样做。有人知道吗?

最佳答案

由于您要过滤和排序的字段位于不同的表中,因此它们不能被单个索引覆盖。

如果添加 STRAIGHT_JOIN 子句,您会强制 MySQLHighScore 中获取每条记录(使用 Score 上的索引code>),在Game中找到匹配的记录,检查是否为42并返回(或忽略)它。

由于 MySQL 无法预先知道有多少记录会匹配,它会假设最坏的情况,只显示计划中 HighScore 记录的总数。

实际上,查询将在返回 50 个数学记录后停止。

关于mysql - 在指定了 ORDER BY 和 LIMIT 并且实际上只需要连接少量行的 JOIN 情况下,MySQL 的行为如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3513293/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com