Mysql 我的SQL命令太长了,有没有简化?
我有一个包含以下列的表(播放器):Mysql 我的SQL命令太长了,有没有简化?,mysql,sql,performance,Mysql,Sql,Performance,我有一个包含以下列的表(播放器): playerID varchar(20) MMR int(10) RANK int(10) 目前有500k排 现在我想更新排名前10k球员的排名栏 因此,我创建了以下SQL命令 START TRANSACTION; UPDATE player SET player.RANK = 10001 WHERE player.Rank < 10001; SET @rank := 0; CREATE TEMPORARY TABLE IF NOT EXIS
playerID varchar(20)
MMR int(10)
RANK int(10)
目前有500k排
现在我想更新排名前10k球员的排名栏
因此,我创建了以下SQL命令
START TRANSACTION;
UPDATE player
SET player.RANK = 10001
WHERE player.Rank < 10001;
SET @rank := 0;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpRank AS (SELECT @rank := @rank + 1 AS rank, PlayerID, MMR
FROM player ORDER BY MMR DESC LIMIT 10000);
UPDATE player, tmpRank
SET player.RANK = tmprank.rank
WHERE player.PlayerID = tmprank.PlayerID;
COMMIT;
指数
Schlüsselname Typ Unique Gepackt Spalte Kardinalität Kollation Null
PRIMARY BTREE Ja Nein PlayerID 479032 A Nein
DeviceID BTREE Ja Nein DeviceID 479032 A Nein
Name BTREE Ja Nein Name 479032 A Nein
MMR BTREE Nein Nein MMR 9580 A Nein
RANK BTREE Nein Nein RANK 2 A Nein
此SQL查询“应如何工作”:
- 通过将每个玩家的等级设置为内部最大值+1(仅设置之前排名的玩家)来“降低等级”
- 创建一个包含排名前10k球员的临时表
- 根据临时表更新玩家表,必要时更改等级
UPDATE player
SET player.RANK = 10001
WHERE player.Rank < 10001;
仅此查询就需要此查询必然非常繁重 你会经常做这个更新吗?如果是这样,我认为在表中有大量更新的列是糟糕的设计。相反,将其放在另一个(“平行”)表中 这样做可能会加快查询速度。甚至可以使用id+rank创建一个表,然后
RENAME table
将其放置到位。这将基本上没有“停机时间”。是的,计算和构建仍然需要很长时间,但用户不会受到影响。我想这是你真正关心的
如果可能,可以动态计算值,而不是存储它。(我怀疑这是否可行,因为你称之为“排名”。这个查询一定非常繁重 你会经常做这个更新吗?如果是这样,我认为在表中有大量更新的列是糟糕的设计。相反,将其放在另一个(“平行”)表中 这样做可能会加快查询速度。甚至可以使用id+rank创建一个表,然后
RENAME table
将其放置到位。这将基本上没有“停机时间”。是的,计算和构建仍然需要很长时间,但用户不会受到影响。我想这是你真正关心的
如果可能,可以动态计算值,而不是存储它。(我怀疑这是否可行,因为你称之为“排名”。为什么只停留在前10k?另外,我不太确定我是否在做你声称的事情。对于查询优化建议,我们需要查看表的定义,包括所有列和所有索引。我同意@GordonLinoff。这似乎是在更新不在前10K中的玩家。假设代码按您所说的做,MMR上的索引将是尝试优化的一个良好开端,因为查询严重依赖于它。您好,感谢您的回答,我编辑了条目postWhy stop in the top 10K?另外,我不太确定我是否在做你声称的事情。对于查询优化建议,我们需要查看表的定义,包括所有列和所有索引。我同意@GordonLinoff。这似乎是在更新不在前10K的玩家。假设代码按您所说的做,MMR上的索引将是尝试优化的一个良好开端,因为查询非常依赖它。您好,谢谢您的回答,我编辑了条目postThank you,这似乎是最好的解决方案。我试过了,用不到3秒钟的时间就创建了一个拥有30万顶级玩家的新表:)谢谢,这似乎是最好的解决方案。我试过了,用不到3秒钟的时间就创建了一个拥有30万顶级玩家的新表:)
UPDATE player
SET player.RANK = 10001
WHERE player.Rank < 10001;
SET @rank := 0;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpRank AS (SELECT @rank := @rank + 1 AS rank, PlayerID, MMR
FROM player ORDER BY MMR DESC LIMIT 10000);
SET @rank := 0;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpRank AS (SELECT @rank := @rank + 1 AS rank, PlayerID, MMR
FROM player ORDER BY MMR DESC LIMIT 10000);
UPDATE player, tmpRank SET player.RANK = tmprank.rank WHERE player.PlayerID = tmprank.PlayerID;