我有一个具有以下结构的表:
我的所有主键都是正确的,每个 int 和日期列都有一个索引,player_groups
中的 (playerId, groupId)
是一个唯一索引。所有表都使用 InnoDB,你看到的关系也是 InnoDB 中的引用。
完整的数据库源,带有数据,大致类似于我将在下面演示的示例:https://www.dropbox.com/s/kzf89occlq4legy/bf4_performance.sql
查询:
查询 #1:
SELECT * FROM playerkills ORDER BY date DESC LIMIT 300;
查询#2:
SELECT p.playerName AS player, p2.playerName AS target, w.weaponName AS weapon, date, headshot, s.serverName AS server FROM playerkills JOIN players p ON playerkills.playerId = p.playerId JOIN players p2 ON playerkills.targetId = p2.playerId JOIN weapons w ON playerkills.weaponId = w.weaponId JOIN servers ON playerkills.serverId = s.serverId ORDER BY date DESC LIMIT 300;
/p>
在我自己的机器上的性能,它有很多资源:
- 查询 #1:0.0016 秒
- 查询 #2:1.3050 秒
实时数据库主机上的性能,资源少得多:
- 查询 #1:0.046 秒
- 查询 #2:1.297 秒
我担心某些东西会严重影响性能,因为它在没有任何 JOIN
语句的情况下工作正常。
任何人都可以对此有更多的了解吗?
ps(编辑)。可能还需要补充一点:该数据库实时更新,每隔几秒更新一次,因此查询结果无法像静态数据查询那样缓存。
编辑 2: 对静态版本(在 localhost
上)的分析给了我这张图片:
EXPLAIN
的输出:
最佳答案
这是子选择可能对您的事业有所帮助的情况之一。与其将所有这些表格连接到完整的 playerkills 表格,您可以子选择最后 300 次玩家击杀,然后基于此加入。所以像这样:
SELECT
p.playerName AS player,
p2.playerName AS target,
w.weaponName AS weapon,
pk.date AS date,
pk.headshot AS headshot,
s.serverName AS server
FROM
(SELECT * FROM playkills ORDER BY date DESC LIMIT 300) AS pk
JOIN players p
ON pk.playerId = p.playerId
JOIN players p2
ON pk.targetId = p2.playerId
JOIN weapons w
ON pk.weaponId = w.weaponId
JOIN servers s
ON pk.serverId = s.serverId
关于MySQL 多重连接速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20079372/