Нужна помощь в оптимизации - PullRequest
1 голос
/ 24 ноября 2011

У меня есть запрос 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 ]

1 голос
/ 24 ноября 2011

Я не вижу смысла в 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;

Убедитесь, что только внутренний запрос использует индекс и работает быстро.Попробуйте и посмотрите, получите ли вы тот же результат и быстрее ли он.

0 голосов
/ 24 ноября 2011
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...