Mysql SQL查询性能
我在数据库中设置了此表,其中包含游戏结果:Mysql SQL查询性能,mysql,sql,Mysql,Sql,我在数据库中设置了此表,其中包含游戏结果: Table Players id ... name 1 .... Alice 2 .... Bob 3 .... Charlie ... etc Table Games Player1 Player2 myscore oppscore result 1 ... 3 .... 25 ... 18 .... W 3 ... 2 .... 15 ... 20 .... L 2 ... 1 .... 17 ... 17 ..
Table Players
id ... name
1 .... Alice
2 .... Bob
3 .... Charlie
... etc
Table Games
Player1 Player2 myscore oppscore result
1 ... 3 .... 25 ... 18 .... W
3 ... 2 .... 15 ... 20 .... L
2 ... 1 .... 17 ... 17 .... T
myscore指的是Player1,oppscore指的是Player2
我想要一个返回玩家最频繁的
对手,以及他们之间的输赢记录。
(我通过对每个对手的第二次查询来获得输赢记录。)
所以我用这个:
SELECT count( * ) p2.name "Opponent",
FROM games, players p1, players p2
WHERE p1.name = ?
AND games.gametype = ?
AND games.player1 = p1.id
AND games.player2 = p2.id
GROUP BY player2, gametype
ORDER BY count( * ) DESC
为了拿起所有游戏(无论谁是玩家1
谁是玩家2)我将每场游戏存储两次:
i、 e.我确实有:
Player1 Player2 myscore oppscore result
1 ... 3 .... 25 ... 18 .... W
3 ... 1 .... 18 ... 25 .... L
3 ... 2 .... 15 ... 20 .... L
2 ... 3 .... 20 ... 15 .... W
2 ... 1 .... 17 ... 17 .... T
1 ... 2 .... 17 ... 17 .... T
我想消除数据的冗余,
从而将数据库大小减少了一半
我尝试过这个(g1是一个类似于桌子的游戏,但是
消除冗余行后)
然后对gv而不是游戏进行查询
哪个有效。。。除此之外(基于一个示例),
超过10倍长(游戏为0.10秒,而游戏为1.4秒
对于gv)
有更好的方法吗?我认为视图很方便,而联合则很慢。把它们加在一起,你会很方便地慢下来。好吧,过度概括 你能忍受什么样的表演 非规范化(在您的例子中是冗余和翻转的)数据当然有它的好处,即以浪费空间为代价提高速度。这是一种杂耍表演 视图的一个特点是,它执行两个表扫描的并集,因为没有过滤器。随着分数的增加,情况会变得更糟。您没有使用索引 当你可以有一个存储的进程,其中的参数集中在
索引的玩家id上时,你真的需要查看所有的数据吗
索引可以成为你最好的朋友。通过mysqlexplain
运行查询会有所帮助
无论如何,我希望这在某种程度上有所帮助。在您看来,使用union all而不是union。这要快得多,因为union all不会检查重复的行,而union通常会检查重复的行。您可以发布针对该视图运行的查询吗?它是相同的查询-只使用视图名称(gv)而不是表名(games)。还有两个复合索引(player1,player2)和(player2,player1)可以产生良好的结果当我创建新的非冗余表进行测试时,我已经忘记了索引,但即使我在(player1,player2)和(player2,player1)上都添加了索引,时间仍然是一样的。当你的查询运行得最好时,我可以告诉你,使用视图的查询正在进行表扫描,这就是缓慢的原因。如果我直接执行UNION查询,这意味着结果不会在两个部分之间合并,那么它使用的是索引,而且速度很快。我想折衷的办法是:为了减少数据库的大小,我可以在处理查询方面投入更多的精力。。。或者只是浪费空间,让代码更简单。谢谢你的回复。谢谢你的提示-联盟似乎快了20%左右。使用UNION创建临时表使用(65,50,55,49,59-avg 56 ms)和UNION ALL使用(45,44,48,44,49-avg 46 ms)对完全相同的查询进行重复试验。以提高速度。不要创建视图。不要把结果只拉分数。在union之前,尝试在第一次查询中从g1筛选player1,在第二次查询中筛选player2,然后将case语句应用于结果表。case语句可能已经强制进行了全表扫描。对-我已经放弃了视图,取而代之的是我使用了一个临时表,其中只有player1的行和player2的索引。。。它现在运行得相当快。我认为是视图本身导致了表扫描。
create view gv as
select * from g1
union
select
player2 player1,
player1 player2,
(case when result = 'T' then 'T'
when result = 'W' then 'L'
when result = 'L' then 'W'
end) result,
oppscore myscore,
myscore oppscore
from g1