需要帮助优化

时间:2011-11-24 05:16:28

标签: mysql sql

我有一个MySQL查询,我想帮助优化。它本质上相当简单,但运行大约需要0.5秒,这将经常运行。

SET @RankNumber:=0; 
SELECT NumberRank,TankName, Color
FROM
(
   SELECT @RankNumber := @RankNumber + 1 AS NumberRank, TankName, Color 
   FROM
   (
      SELECT TankID, MapID, Color, TankName
      FROM MAPDATA
      INNER JOIN Tank ON Tank.ID = MapData.TankID
      WHERE MapID = 3
      ORDER BY Rank DESC, TotalPP DESC
   ) Query1
) final
WHERE Color = 3
LIMIT 10;

基本上我正在做的是,我给每个记录一个数字(RankNumber),然后我从数据库中选择地图为3的所有坦克,然后我给它们每个人在地图中的数字按等级和经验值排序。然后我过滤掉除了我想要的颜色以外的所有颜色,这就是为什么我基本上有三个级别所以我可以得到每一行。

你有前10名,这很简单1-10然后你有顶紫色,看起来更像1,7,10,25,36等等,因为前10名不是所有颜色的前10名。合理?这需要0.5秒才能完成,人们的命中率可能达到每分钟10-30次。

1   PRIMARY <derived2>  ALL                 31220   Using where
2   DERIVED <derived3>  ALL                 31220   
3   DERIVED Tank    ALL PRIMARY,idx_TankID              9863    Using temporary; Using filesort
3   DERIVED MAPDATA ref PRIMARY,MapID,TankID,idx_mapdata    PRIMARY 8   microtanksbeta.Tank.ID  1   

这是我对该查询的说明。任何帮助将被赞赏加快这一点。如果有一种方法我可以告诉它将这个查询保留在内存中,或者某些东西只是工作,所以它不是那么慢。

显示创建表格

'MapData', 'CREATE TABLE `mapdata` (
  `MapID` int(11) NOT NULL,
  `TankID` int(11) NOT NULL,
  `Color` tinyint(4) NOT NULL,
  `X` int(11) DEFAULT ''-1'',
  `Y` int(11) DEFAULT ''-1'',
  `Rank` tinyint(4) NOT NULL DEFAULT ''0'',
  `Health` int(11) NOT NULL DEFAULT ''1000'',
  `Armors` tinyint(4) NOT NULL DEFAULT ''0'',
  `Duals` tinyint(4) NOT NULL DEFAULT ''0'',
  `Missiles` tinyint(4) NOT NULL DEFAULT ''0'',
  `Homings` tinyint(4) NOT NULL DEFAULT ''0'',
  `Radars` tinyint(4) NOT NULL DEFAULT ''0'',
  `Beacons` tinyint(4) NOT NULL DEFAULT ''0'',
  `HasRankKill` bit(1) NOT NULL DEFAULT b''0'',
  `TotalPP` bigint(20) NOT NULL DEFAULT ''0'',
  `RankPP` bigint(20) NOT NULL DEFAULT ''0'',
  `KillCount` int(11) NOT NULL DEFAULT ''0'',
  `DeathCount` int(11) NOT NULL DEFAULT ''0'',
  `TimePlayed` time NOT NULL DEFAULT ''00:00:00'',
  `EnabledEquipment` tinyint(4) NOT NULL DEFAULT ''0'',
  `Prestige` tinyint(4) NOT NULL DEFAULT ''0'',
  PRIMARY KEY (`MapID`,`TankID`,`Color`),
  KEY `MapID` (`MapID`),
  KEY `TankID` (`TankID`),
  KEY `idx_mapdata` (`MapID`,`Color`,`TankID`),
  CONSTRAINT `mapdata_ibfk_1` FOREIGN KEY (`MapID`) REFERENCES `maps` (`ID`) ON DELETE CASCADE,
  CONSTRAINT `mapdata_ibfk_2` FOREIGN KEY (`TankID`) REFERENCES `tank` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1'


'Tank', 'CREATE TABLE `tank` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Username` text NOT NULL,
  `TankName` text NOT NULL,
  `KillAward` int(11) DEFAULT ''0'',
  `DeathAward` int(11) DEFAULT ''0'',
  `TimeAward` int(11) DEFAULT ''0'',
  `Stars` int(11) DEFAULT ''0'',
  `Trophy` int(11) DEFAULT ''0'',
  `Dot` int(11) DEFAULT ''0'',
  `Cartographer` int(11) DEFAULT ''0'',
  `OtherAwards` int(11) DEFAULT ''0'',
  `Banned` bit(1) DEFAULT b''0'',
  `BanExpiration` datetime DEFAULT NULL,
  `BanExplination` text,
  `Deleted` bit(1) DEFAULT b''0'',
  `DeletedDate` datetime DEFAULT NULL,
  `CreationDate` datetime NOT NULL DEFAULT ''2011-05-24 00:00:00'',
  PRIMARY KEY (`ID`),
  KEY `idx_TankName` (`TankName`(40)),
  KEY `idx_UNTankName` (`Username`(60),`TankName`(40)),
  KEY `idx_TankID` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=23239 DEFAULT CHARSET=latin1'

2 个答案:

答案 0 :(得分:1)

我认为3级没有任何用处,2应该足够了。此外,我已将联接移出内部选择以使其更快。

SET @RankNumber:=0; 
SELECT inner.NumberRank, tank.TankName, inner.Color
 FROM (SELECT @RankNumber := @RankNumber + 1 AS NumberRank, TankID, Color
         FROM MAPDATA
        WHERE MapID = 3
        ORDER BY Rank DESC, TotalPP DESC
      ) inner
INNER JOIN Tank ON Tank.ID = inner.TankID
WHERE inner.Color = 3
LIMIT 10;

确保内部查询单独使用索引并且速度很快。 尝试一下,看看你是否得到相同的结果,如果它更快。

答案 1 :(得分:0)

SELECT NumberRank, TankName, Color
FROM (
    SELECT @RankNumber := @RankNumber + 1 AS NumberRank, TankID, Color
    FROM MAPDATA, (SELECT @RankNumber:=0) as init
    WHERE MapID = 3
    HAVING Color = 3
    ORDER BY Rank DESC, TotalPP DESC
    LIMIT 10
) ranks JOIN Tank ON Tank.ID = TankID