我怎样才能改进我的查询以减少执行时间,并且我仍然可以使用多个表将结果分成几页
How can I improve my query so it takes less time to execute, and I can still divide the result into pages using multiple tables
我正在尝试创建一个 PHP 网站,该网站允许用户查看在线游戏玩家的排行榜(按他们的 运行 国王排序。
运行国王由以下部分组成:
- 等级(挑战者、G运行dmaster、大师、钻石、白金、黄金、白银、青铜和铁)
- 等级(I、II、III 和 IV)
- 联赛积分(整数)
每个 运行k 包含 4 个等级,除了 Challenger、G运行dmaster 和 Master,它们只包含 1 个等级 (I)。
我将玩家数据存储在 table 秒中,每个数据仅包含有关特定等级内玩家的信息。所以我的 table 是这样命名的:
- master_league_region
- diamond_i_league_region
- diamond_ii_league_region
- 等等
每个 table 中的条目数可以是 0 到任何值。
我之前尝试将所有数据存储在一个 table 中(将近一百万个条目),但是执行查询大约需要 30 秒。现在他们大约需要 9 秒,但这仍然太长了。
由于我需要将排行榜分成几页(每页显示 100 个条目),除了对所有数据进行一次大查询之外,我真的想不出任何其他解决方案。
这非常适合对结果进行分页,但此查询大约需要 9 秒,而我的目标是低于 1 或 2 秒。
我在这里呆了几天了,我真的 运行 不知道如何改进我的查询,这样我仍然可以轻松地将它分成几页:
$sql = "SELECT * FROM challenger_league_$region
UNION
SELECT * FROM grandmaster_league_$region
UNION
SELECT * FROM master_league_$region
UNION
SELECT * FROM diamond_i_league_$region
UNION
SELECT * FROM diamond_ii_league_$region
UNION
SELECT * FROM diamond_iii_league_$region
UNION
SELECT * FROM diamond_iv_league_$region
UNION
SELECT * FROM platinum_i_league_$region
UNION
SELECT * FROM platinum_ii_league_$region
UNION
SELECT * FROM platinum_iii_league_$region
UNION
SELECT * FROM platinum_iv_league_$region
UNION
SELECT * FROM gold_i_league_$region
UNION
SELECT * FROM gold_ii_league_$region
UNION
SELECT * FROM gold_iii_league_$region
UNION
SELECT * FROM gold_iv_league_$region
UNION
SELECT * FROM silver_i_league_$region
UNION
SELECT * FROM silver_ii_league_$region
UNION
SELECT * FROM silver_iii_league_$region
UNION
SELECT * FROM silver_iv_league_$region
UNION
SELECT * FROM bronze_i_league_$region
UNION
SELECT * FROM bronze_ii_league_$region
UNION
SELECT * FROM bronze_iii_league_$region
UNION
SELECT * FROM bronze_iv_league_$region
UNION
SELECT * FROM iron_i_league_$region
UNION
SELECT * FROM iron_ii_league_$region
UNION
SELECT * FROM iron_iii_league_$region
UNION
SELECT * FROM iron_iv_league_$region
ORDER BY case WHEN tier = 'CHALLENGER' THEN '100'
WHEN tier = 'GRANDMASTER' THEN '101'
WHEN tier = 'MASTER' THEN '102'
WHEN tier = 'DIAMOND' AND rank = 'I' THEN '103'
WHEN tier = 'DIAMOND' AND rank = 'II' THEN '104'
WHEN tier = 'DIAMOND' AND rank = 'III' THEN '105'
WHEN tier = 'DIAMOND' AND rank = 'IV' THEN '106'
WHEN tier = 'PLATINUM' AND rank = 'I' THEN '107'
WHEN tier = 'PLATINUM' AND rank = 'II' THEN '108'
WHEN tier = 'PLATINUM' AND rank = 'III' THEN '109'
WHEN tier = 'PLATINUM' AND rank = 'IV' THEN '110'
WHEN tier = 'GOLD' AND rank = 'I' THEN '111'
WHEN tier = 'GOLD' AND rank = 'II' THEN '112'
WHEN tier = 'GOLD' AND rank = 'III' THEN '113'
WHEN tier = 'GOLD' AND rank = 'IV' THEN '114'
WHEN tier = 'SILVER' AND rank = 'I' THEN '115'
WHEN tier = 'SILVER' AND rank = 'II' THEN '116'
WHEN tier = 'SILVER' AND rank = 'III' THEN '117'
WHEN tier = 'SILVER' AND rank = 'IV' THEN '118'
WHEN tier = 'BRONZE' AND rank = 'I' THEN '119'
WHEN tier = 'BRONZE' AND rank = 'II' THEN '120'
WHEN tier = 'BRONZE' AND rank = 'III' THEN '121'
WHEN tier = 'BRONZE' AND rank = 'IV' THEN '122'
WHEN tier = 'IRON' AND rank = 'I' THEN '123'
WHEN tier = 'IRON' AND rank = 'II' THEN '124'
WHEN tier = 'IRON' AND rank = 'III' THEN '125'
WHEN tier = 'IRON' AND rank = 'IV' THEN '126'
ELSE '200'
END, leaguePoints DESC
LIMIT $startFrom, 100;";
存储单个实体(例如“用户”)数据的正确方法是将其全部放在一个 table 中。一百万行对于现代数据库来说并不是很大的行数。这应该是您优化的起点。
很有可能,您只需要 table 上的正确索引。
您似乎对这些等级有订单。此信息应存储在单独的参考 tables.
中
多个 table 不是一个好主意,原因有很多,包括:
- SQL 针对较少的大 table 而不是针对大量较小的 table 进行了优化。
- 访问所有数据非常棘手,因为您需要
union
数以亿计的 table 在一起,这些数据可能会随时间发生变化。
- 添加或修改列很棘手,因为您必须更改数以亿计的 tables。
- 很难优化,因为每个 table 中的数据相对较小。读取半空数据页的开销可能会支配您的查询。
我建议您了解或回顾规范化的原则,然后重新开始您的数据模型。
我正在尝试创建一个 PHP 网站,该网站允许用户查看在线游戏玩家的排行榜(按他们的 运行 国王排序。
运行国王由以下部分组成:
- 等级(挑战者、G运行dmaster、大师、钻石、白金、黄金、白银、青铜和铁)
- 等级(I、II、III 和 IV)
- 联赛积分(整数)
每个 运行k 包含 4 个等级,除了 Challenger、G运行dmaster 和 Master,它们只包含 1 个等级 (I)。
我将玩家数据存储在 table 秒中,每个数据仅包含有关特定等级内玩家的信息。所以我的 table 是这样命名的:
- master_league_region
- diamond_i_league_region
- diamond_ii_league_region
- 等等
每个 table 中的条目数可以是 0 到任何值。
我之前尝试将所有数据存储在一个 table 中(将近一百万个条目),但是执行查询大约需要 30 秒。现在他们大约需要 9 秒,但这仍然太长了。
由于我需要将排行榜分成几页(每页显示 100 个条目),除了对所有数据进行一次大查询之外,我真的想不出任何其他解决方案。
这非常适合对结果进行分页,但此查询大约需要 9 秒,而我的目标是低于 1 或 2 秒。
我在这里呆了几天了,我真的 运行 不知道如何改进我的查询,这样我仍然可以轻松地将它分成几页:
$sql = "SELECT * FROM challenger_league_$region
UNION
SELECT * FROM grandmaster_league_$region
UNION
SELECT * FROM master_league_$region
UNION
SELECT * FROM diamond_i_league_$region
UNION
SELECT * FROM diamond_ii_league_$region
UNION
SELECT * FROM diamond_iii_league_$region
UNION
SELECT * FROM diamond_iv_league_$region
UNION
SELECT * FROM platinum_i_league_$region
UNION
SELECT * FROM platinum_ii_league_$region
UNION
SELECT * FROM platinum_iii_league_$region
UNION
SELECT * FROM platinum_iv_league_$region
UNION
SELECT * FROM gold_i_league_$region
UNION
SELECT * FROM gold_ii_league_$region
UNION
SELECT * FROM gold_iii_league_$region
UNION
SELECT * FROM gold_iv_league_$region
UNION
SELECT * FROM silver_i_league_$region
UNION
SELECT * FROM silver_ii_league_$region
UNION
SELECT * FROM silver_iii_league_$region
UNION
SELECT * FROM silver_iv_league_$region
UNION
SELECT * FROM bronze_i_league_$region
UNION
SELECT * FROM bronze_ii_league_$region
UNION
SELECT * FROM bronze_iii_league_$region
UNION
SELECT * FROM bronze_iv_league_$region
UNION
SELECT * FROM iron_i_league_$region
UNION
SELECT * FROM iron_ii_league_$region
UNION
SELECT * FROM iron_iii_league_$region
UNION
SELECT * FROM iron_iv_league_$region
ORDER BY case WHEN tier = 'CHALLENGER' THEN '100'
WHEN tier = 'GRANDMASTER' THEN '101'
WHEN tier = 'MASTER' THEN '102'
WHEN tier = 'DIAMOND' AND rank = 'I' THEN '103'
WHEN tier = 'DIAMOND' AND rank = 'II' THEN '104'
WHEN tier = 'DIAMOND' AND rank = 'III' THEN '105'
WHEN tier = 'DIAMOND' AND rank = 'IV' THEN '106'
WHEN tier = 'PLATINUM' AND rank = 'I' THEN '107'
WHEN tier = 'PLATINUM' AND rank = 'II' THEN '108'
WHEN tier = 'PLATINUM' AND rank = 'III' THEN '109'
WHEN tier = 'PLATINUM' AND rank = 'IV' THEN '110'
WHEN tier = 'GOLD' AND rank = 'I' THEN '111'
WHEN tier = 'GOLD' AND rank = 'II' THEN '112'
WHEN tier = 'GOLD' AND rank = 'III' THEN '113'
WHEN tier = 'GOLD' AND rank = 'IV' THEN '114'
WHEN tier = 'SILVER' AND rank = 'I' THEN '115'
WHEN tier = 'SILVER' AND rank = 'II' THEN '116'
WHEN tier = 'SILVER' AND rank = 'III' THEN '117'
WHEN tier = 'SILVER' AND rank = 'IV' THEN '118'
WHEN tier = 'BRONZE' AND rank = 'I' THEN '119'
WHEN tier = 'BRONZE' AND rank = 'II' THEN '120'
WHEN tier = 'BRONZE' AND rank = 'III' THEN '121'
WHEN tier = 'BRONZE' AND rank = 'IV' THEN '122'
WHEN tier = 'IRON' AND rank = 'I' THEN '123'
WHEN tier = 'IRON' AND rank = 'II' THEN '124'
WHEN tier = 'IRON' AND rank = 'III' THEN '125'
WHEN tier = 'IRON' AND rank = 'IV' THEN '126'
ELSE '200'
END, leaguePoints DESC
LIMIT $startFrom, 100;";
存储单个实体(例如“用户”)数据的正确方法是将其全部放在一个 table 中。一百万行对于现代数据库来说并不是很大的行数。这应该是您优化的起点。
很有可能,您只需要 table 上的正确索引。
您似乎对这些等级有订单。此信息应存储在单独的参考 tables.
中多个 table 不是一个好主意,原因有很多,包括:
- SQL 针对较少的大 table 而不是针对大量较小的 table 进行了优化。
- 访问所有数据非常棘手,因为您需要
union
数以亿计的 table 在一起,这些数据可能会随时间发生变化。 - 添加或修改列很棘手,因为您必须更改数以亿计的 tables。
- 很难优化,因为每个 table 中的数据相对较小。读取半空数据页的开销可能会支配您的查询。
我建议您了解或回顾规范化的原则,然后重新开始您的数据模型。