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上时,你真的需要查看所有的数据吗

索引可以成为你最好的朋友。通过mysql
explain
运行查询会有所帮助


无论如何,我希望这在某种程度上有所帮助。

在您看来,使用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