我有以下要优化的查询:
SELECT
*, @rownum := @rownum + 1 AS rank
FROM (
SELECT
SUM(a.id = 1) as KILLS,
SUM(a.id = 2) as DEATHS,
SUM(a.id = 3) as WINS,
tb1.totalPlaytime,
p.playerName
FROM
(
SELECT
player_id,
SUM(pg.timeEnded - pg.timeStarted) as totalPlaytime
FROM playergame pg
INNER JOIN player p
ON pg.player_id = p.id
WHERE pg.game_id IN(1, 2, 3)
GROUP BY
p.id
ORDER BY
p.playerName ASC
) tb1
INNER JOIN playeraction pa
ON pa.player_id = tb1.player_id
INNER JOIN action a
ON pa.action_id = a.id
INNER JOIN player p
ON pa.player_id = p.id
GROUP BY
p.id
ORDER BY
KILLS DESC) tb2
WHERE tb2.playerName LIKE "%"
不知怎的,我感觉这不适合mysql。我在不同的表格中保留了很多动作以获得良好的统计方法,但这会减慢一切。 (也许是大数据?)
这是我的模型
现在我尝试执行以下操作:
在视图中合并联接
我将许多JOINS组合到一个视图中。这没有给我任何改进。
为表格编制索引
我将经常使用的键编入索引,这确实加快了速度,但我无法将整个结果集设置为低于0.613秒。
从操作表开始并使用左连接
这给了我一个不同的方法但是连接仍然很慢(第一个例子仍然是最快的)
索引:
欢迎任何提示,提示,补充,改进
答案 0 :(得分:1)
我删除了之前的答案,因为它错了而且没有帮助,我在这里只是在评论中总结我们的对话以及我自己的其他评论
有几种方法可以加快查询速度。
关于您在问题中写的查询:
在内部查询中删除ORDER BY
删除内部查询中的INNER JOIN
并将GROUP BY p.id
替换为GROUP BY player_id
关于索引有意义的地方和没有意义的地方几乎没有。
在你的情况下,在表gameid
上的playergame
上建立索引是没有意义的,因为这可能会返回大量的行。这就是你可以对最内在的查询做的所有事情。
如果你知道你对表的期望,即它们可能面临的数据量,那么连接也可以稍微优化一下。你可能会认为这是一个问题,你在FPS的MMO游戏背后建立数据库。 MMO每场比赛将有数百万用户,FPS将只有少数用户。此外,不同类型的游戏可能具有不同的动作。这意味着您可以尝试通过使索引更精确来优化查询。如果您能够在action
的内部联接中定义gameid IN (...)
,那么在元组(gameid, id)
上创建索引可能会有所帮助。
WHERE
子句中的Wildcart。您可以尝试在playername
上创建一个索引,但只有在搜索字符串末尾使用通配符时才能生成索引,因为一开始您需要一个单独的索引,并希望查询优化器能够每次进行查询时都要足够智能地在它们之间切换。
请记住,更多索引意味着插入和删除速度变慢,因此请尽可能少。
另一件事就是重新设计一下这个结构。您仍然可以保持数据库规范化,但是如果有一个包含某些游戏摘要的表格可能会很有用。您可能有一个表格,其中包含昨天之前发生的游戏摘要,您的查询只会汇总今天的数据,然后根据需要加入两个表格。然后,您可以通过在时间戳上创建和索引或按日分区来优化它。一切都取决于你期望的负荷。
主题相当深刻,所以一切都取决于数据背后的故事。