mysql - self 加入速度慢得令人痛苦

标签 mysql sql

我有一个名为“match_players”的关系表,约有 20000 行。有一个名为“hero_id”的列,代表玩家在比赛中选择的英雄。所有字段均已编入索引。

我需要建立另一个表,其中包含两个英雄的所有组合,并统计他们在同一队伍中的次数、他们成为敌人的次数等。

我当前的查询在 8 核 SSD 服务器上大约需要 90 秒。我想这与 MySQL 在对结果进行分组之前在内部构建这个包含所有组合的庞大表有关。

是否有另一种方法来收集行值的组合,也许MySQL只是扫描表,记录发现的新组合?欢迎任何意见。

表“match_players”:

match_id | team | position | player_id | hero_id |

56427859 |    1 |        1 |    546107 |      17 |
56427859 |    1 |        2 |    469333 |      81 |
56427859 |    1 |        3 |    227526 |      60 |
56427859 |    1 |        4 |    193739 |      32 |
56427860 |    0 |        0 |    473923 |      11 |
56427860 |    0 |        1 |    292764 |      93 |
56427860 |    0 |        2 |    138018 |      26 |
56427860 |    0 |        3 |    326510 |      96 |

etc...

查询:

SELECT mp1.hero_id, mp2.hero_id
FROM match_players mp1
INNER JOIN match_players mp2
ON mp1.hero_id < mp2.hero_id
WHERE mp1.team = mp2.team
GROUP BY mp1.hero_id, mp2.hero_id

解释:

id | select_type | table | type | possible_keys      | key        | key_len | ref                        |  rows | Extra

 1 |      SIMPLE |   mp1 |  ALL | faction_id,hero_id |       NULL |    NULL |                       NULL | 34060 | Using temporary; Using filesort
 1 |      SIMPLE |   mp2 |  ref | faction_id,hero_id | faction_id |       1 | beta_dota_2.mp1.faction_id |  3499 | Using where

更新:

由于我只需要一起参加比赛的英雄,因此我将查询更新为以下内容,速度要快得多。我认为它会在零点几秒内完成。

SELECT mp1.hero_id, mp2.hero_id
FROM match_players mp1
INNER JOIN match_players mp2
ON mp1.hero_id < mp2.hero_id
WHERE mp1.team = mp2.team AND mp1.match_id = mp2.match_id
GROUP BY mp1.hero_id, mp2.hero_id

不过,我仍然想知道,如果我想要所有英雄的组合列表,无论是否在同一场比赛中,最好的方法是什么?对于任何大于几千行的表,我的原始查询显然是不可行的。

最佳答案

对于此查询:

SELECT mp1.hero_id, mp2.hero_id
FROM match_players mp1 INNER JOIN
     match_players mp2
     ON mp1.hero_id < mp2.hero_id AND
        mp1.team = mp2.team
GROUP BY mp1.hero_id, mp2.hero_id;

您需要 match_players(team, Hero_id) 上的复合索引。这是一个起点。

我认为,性能问题可能是由于一场比赛中许多玩家选择了同一个“英雄”。如果这是可能的,那么对于计数,您需要 count(distinct match_id) 而不是 count(*)。更重要的是,这会对性能产生很大影响——具体取决于团队的规模。

您可能需要运行此查询来了解这种情况发生的频率:

select cnt, count(*)
from (select match_id, hero_id, count(*) as cnt
      from match_players
      group by match_id, hero_id
     ) mh
group by cnt
order by cnt desc;

关于mysql - self 加入速度慢得令人痛苦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36818132/

相关文章:

mysql - 没有order by子句时先返回哪个字段?

sql - 如何跨中间表连接的三个表进行查询?

mysql - 外部行没有被删除(有级联),为什么?

mysql - SQL 在表上同时创建多列索引和单列索引

php - 使用 Android 从在线 MySQL 数据库中获取数据

sql - Hadoop - 在具有可变列的 CSV 文件集合上公开 SQL 接口(interface)

c# - 转义转义符不起作用——SQL LIKE 运算符

MySQL Try-Catch 存储过程 - SQL 语法错误 1064

sql - SQLite3 -batch CLI 选项有什么作用?

python - 我需要使用 python 将 sql 表导出到管道分隔的文本文件中,包括列名