我有一个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'
答案 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