我怎样才能改进我的查询以减少执行时间,并且我仍然可以使用多个表将结果分成几页

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 网站,该网站允许用户查看在线游戏玩家的排行榜(按他们的 运行 国王排序。

运行国王由以下部分组成:

每个 运行k 包含 4 个等级,除了 Challenger、G运行dmaster 和 Master,它们只包含 1 个等级 (I)。

我将玩家数据存储在 table 秒中,每个数据仅包含有关特定等级内玩家的信息。所以我的 table 是这样命名的:

每个 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 中的数据相对较小。读取半空数据页的开销可能会支配您的查询。

我建议您了解或回顾规范化的原则,然后重新开始您的数据模型。