在mysql中减少此查询的执行时间的方法

时间:2015-08-05 02:27:00

标签: mysql

前段时间我需要一些帮助来构建自定义查询。这个查询到目前为止工作正常。 当我运行查询(在一个过程中)时,我收到错误:

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已经是索引

1 个答案:

答案 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并使用NULL0翻译为IFNULL(foo.cnt, 0)

如果你需要索引行,你可以单独添加一个额外的外部查询,但我个人更喜欢在处理查询结果的应用程序中处理外部SQL。