提高Mysql查询性能
Posted
技术标签:
【中文标题】提高Mysql查询性能【英文标题】:Improve Mysql query performance 【发布时间】:2014-08-14 00:41:50 【问题描述】:我有这张高分表
CREATE TABLE IF NOT EXISTS
高分(
盖int(11) NOT NULL,
用户名varchar(50) NOT NULL,
用户IDint(6) NOT NULL,
得分int(16) NOT NULL,
dateaddedtimestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (
盖,
用户名), KEY
得分(
盖,
得分) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
它有超过 200 万行。当我运行以下查询时,大约需要 4.5 秒。我希望这里有人对如何通过更改查询、添加/修改索引或更改存储引擎来提高速度有一些建议?
选择 h.userid,h.username AS user ,count(h.username) AS scorecount 从 高分 h INNER JOIN (select lid, min(score) AS maxscore FROM highscores group by lid) t on h.lid = t.lid and h.score = t.maxscore 按 h.username 分组 ORDER BY scorecount DESC
这里的要求是解释:
【问题讨论】:
你为什么有min(score) AS maxscore
?这会导致所谓的“认知失调”。您正在调用最小值。
首先查看EXPLAIN
告诉您的有关您的声明的内容……
我有 min(score) AS maxscore 因为我重用了另一个游戏中的查询,分数越高越好。只是我的懒惰/疏忽。为了清楚起见,我会改变它。
【参考方案1】:
这是您的查询:
SELECT h.userid, h.username AS user, count(h.username) AS scorecount
FROM highscores h INNER JOIN
(select lid, min(score) AS maxscore
FROM highscores
group by lid
) t
on h.lid = t.lid and h.score = t.maxscore
group by h.username
ORDER BY scorecount DESC;
这似乎是在回答这个问题:“用户有多少次在表格中获得最高(或最低)分数?”。这表明您可以将查询重写为:
select hs.userid, hs.username, count(*) as scorecount
from highscores hs
where not exists (select 1 from highscores hs2 where hs2.lid = hs.lid and hs2.score > hs.score)
group by hs.userid, hs.username
order by scorecount desc;
您现有的索引应该可以很好地解决这个问题。 userid, username
上的索引会帮助一些数据库引擎,但我认为 mysql 不会利用它。
【讨论】:
遗憾的是,您的新查询耗时 181.7252 秒,但我确实执行了相同的结果 你知道只有一个用户在任何给定的lid
中得分最高吗?
有可能打成平手或者同分【参考方案2】:
我最终做的是缓存查询,让它每 10 分钟更新一次。可能有更好的解决方案,但我无法让查询更快。
【讨论】:
【参考方案3】:先生,我不认为调整您的查询是您正确的解决方案。你刚才说你在那个分数表中有 200 万行。您能想象在执行查询时检查每行的单元格/行需要多长时间?
您需要的是数据库规范化和设计表格的正确方法
http://en.wikipedia.org/wiki/Database_normalization
【讨论】:
我真的不知道如何进一步规范化表格。 您可以添加您在那里使用的其他表的架构吗?所以我们可以弄清楚我们可以用它们做什么......你可能想要将分数从最低分数到最高分数分开。 好吧,lid 是“级别 id”(一个 int(6)),就像用户获得分数的级别一样。每个级别都有自己的排行榜和全球排行榜。我还有一个标准的用户表,其中存储了所有用户信息。我选择将用户 id(uid) 和用户名都存储在 highscores 表中,以尝试使查询更简单。以上是关于提高Mysql查询性能的主要内容,如果未能解决你的问题,请参考以下文章