前段时间我需要一些帮助来构建自定义查询。这个查询到目前为止工作正常。 当我运行查询(在一个过程中)时,我收到错误:
Error Code: 2013. Lost connection to MySQL server during query
我通过ssh访问my.ini是只读的(因为我的数据库位于共享主机“godaddy”中)所以我无法增加执行时间(实际为60)
是否有一种方法可以优化此查询以使其更快?
查询是:
SELECT @curRank := @curRank + 1 as rank, p.nick,(kills + ((p.vpos - p.vneg)*5) + (top * 5) - deaths) as score
FROM (SELECT
(SELECT uuid FROM players WHERE players.uuid = p.uuid LIMIT 1) as uuid,
(SELECT nick FROM nicks n WHERE n.pid = p.id ORDER BY id DESC LIMIT 1) as nick,
(SELECT COUNT(*) FROM kills k WHERE k.pid = p.id ) as kills,
(SELECT COUNT(*) FROM deaths d WHERE d.pid = p.id ) as deaths,
(SELECT COUNT(*) FROM headshots h WHERE h.pid = p.id ) as hs,
(SELECT COUNT(*) FROM votos vp WHERE vp.vid = p.id AND tipo="p") as vpos,
(SELECT COUNT(*) FROM votos vn WHERE vn.vid = p.id AND tipo="n") as vneg,
(SELECT COUNT(*) FROM top_rounds t WHERE t.pid = p.id ) as top,
(SELECT @curRank := 0) as rank
FROM players p
) p ORDER BY score DESC LIMIT 30;
注意:所有pid和p.id已经是索引
答案 0 :(得分:1)
未经测试(由于缺少样本数据):
SELECT p.nick,
(IFNULL(k.cnt, 0)
+ ((IFNULL(vpos.cnt, 0) - IFNULL(vneg.cnt, 0))*5)
+ (IFNULL(t.cnt, 0) * 5) - IFNULL(d.cnt, 0) AS score
FROM players p
LEFT JOIN (
SELECT pid, COUNT(*) AS cnt
FROM kills
GROUP BY pid
) AS k ON p.id = k.pid
⋮
LEFT JOIN (
SELECT pid, COUNT(*) AS cnt
FROM top_rounds
GROUP BY pid
) AS t ON p.id = t.pid
ORDER BY score DESC
LIMIT 30
即。确保每个内部查询仅对所有玩家运行一次。每个子查询都会生成一个表,该表将玩家ID映射到相应的计数。由于可能没有匹配的行,我们必须使用LEFT JOIN
并使用NULL
将0
翻译为IFNULL(foo.cnt, 0)
。
如果你需要索引行,你可以单独添加一个额外的外部查询,但我个人更喜欢在处理查询结果的应用程序中处理外部SQL。