2012-09-29 32 views
1

我在我的Nexuiz统计Web项目中遇到了MySQL请求问题。 我wan't以产生实时的请求采取的时间 (配310000项的请求,从3到7秒需要)losts统计表 这里是SQL请求我希望优化等是否可以优化我的SQL请求?如果是的话,怎么样?

SELECT n.name, d.times_kill, d.times_dead, d.kd, d.times_cap, d.points 
FROM 
(SELECT f.player player, f.times_kill, f.times_dead, f.kd, g.times_cap, ((f.points * (7/3)) + POW(g.times_cap, 1.5)) points 
FROM 
    (SELECT k.player player, k.times_kill, d.times_dead, (k.times_kill/d.times_dead) kd, ((k.times_kill/d.times_dead) * k.times_kill) points 
    FROM 
     (SELECT player, count(*) times_kill 
     FROM `nexstat`.`dc_events` 
      WHERE event = 'KILL' AND server = '2' 
      GROUP BY player 
      ORDER BY times_kill DESC 
     ) k 
     JOIN 
     (SELECT player, count(*) times_dead 
     FROM `nexstat`.`dc_events` 
      WHERE event = 'DEAD' AND server = '2' 
      GROUP BY player 
      ORDER BY times_dead DESC 
     ) d 
     ON d.player = k.player 
     ORDER BY points DESC 
    ) f 
    JOIN 
    (SELECT player, count(*) times_cap 
    FROM `nexstat`.`dc_events` 
     WHERE event = 'CAP' AND server = '2' 
     GROUP BY player ORDER BY times_cap DESC 
    ) g 
    ON f.player = g.player 
) d 
JOIN 
(SELECT * FROM `nexstat`.`dc_players` WHERE main = 1 
) n 
ON d.player = n.id 
GROUP BY id 
ORDER BY points DESC 

数据库模型在这里:

CREATE TABLE IF NOT EXISTS `dc_events` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `player` int(11) NOT NULL, 
    `event` enum('CAP','KILL','DEAD','DROP','PICKUP','CHANGE','JOIN','LEAVE') NOT NULL, 
    `param0` int(11) DEFAULT NULL, 
    `server` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `event` (`event`), 
    KEY `server` (`server`), 
    KEY `player` (`player`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED AUTO_INCREMENT=1 ; 


CREATE TABLE IF NOT EXISTS `dc_players` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `main` tinyint(1) NOT NULL DEFAULT '1', 
    `name` varchar(512) NOT NULL, 
    `website` varchar(512) NOT NULL, 
    `email` varchar(512) NOT NULL, 
    `clan` varchar(512) NOT NULL, 
    `country` varchar(2) NOT NULL, 
    UNIQUE KEY `name` (`name`), 
    KEY `website` (`website`), 
    KEY `email` (`email`), 
    KEY `id` (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

将是冷静,如果有人可以帮助我;)

+2

对于这些类型的问题,*重要的*包括架构,查询计划/解释,以及一些数据的想法(计数和分布)..确保这些信息*包含在帖子本身*中。 – 2012-09-29 01:37:10

回答

0

这或许有助于简化您的查询。由于我不完全理解它的逻辑,所以我可能会离开某个地方。不过,我认为下面基本上做了你的大查询,但没有所有派生表。额外的ORDER BY子句将花费你很多,因为它们强制MySQL重复执行数据,而不是在最后一次执行。由于数据只是按最外层查询中的点重新排序,它们也不能帮助您回答问题。

SELECT dc_player.name AS player_name, 
     times_kill, 
     times_dead, 
     times_cap, 
     times_kill/times_dead AS kd, 
     ((((times_kill/times_dead) * times_kill) * (7/3)) + POW(times_cap, 1.5)) AS points 
FROM (
    SELECT player, 
      SUM(IF(event='KILL',1,0)) AS times_kill, 
      SUM(IF(event='DEAD',1,0)) AS times_dead, 
      SUM(IF(event='CAP',1,0)) AS times_cap 
    FROM dc_events 
    GROUP BY player 
) AS events 
JOIN dc_player 
    ON dc_player.id = events.player 
ORDER BY points; 

你为什么在2012年使用MyISAM? InnoDB现在是默认设置,它支持更多的索引选项和引用完整性(因为您在这里有外键关系,所以您会希望这样做)。你至少需要在dc_events.player上有一个索引(InnoDB外键默认是一个索引)。

相关问题