MySQL 8.0.15 Дамба медленного выбора запроса - PullRequest
1 голос
/ 30 марта 2019

Девиз запроса очень прост, чтобы узнать последнюю запись в столбце внешнего ключа. псевдокод, который я могу сказать, это

select vehicleid , last_journey_point , last_journey_time from journeyTable.

вот мой SQL-оператор

- loconumber - индексированный столбец - tripserla - первичный ключ автономного номера int (11) - таблица locojourney содержит 400 000 записей

- приведенный ниже блок кода выполняется за 19 секунд

with LocomotiveLastRun AS(
     -- this block of code runs in 0.016 sec
    SELECT locojourney.loconumber , MAX(locojourney.journeyserla) as lastrunid
      FROM locojourney GROUP BY loconumber)

  SELECT locojourney.CurrentCombiners , locojourney.JourneySerla , 
         locojourney.From_RunPoint , locojourney.NEXT_RunPoint 
   FROM  LocomotiveLastRun FORCE INDEX(lastrunid)
   JOIN  locojourney FORCE INDEX(PRIMARY) ON x.lastrunid = locojourney.journeyserla 
  WHERE  locojourney.ishoc = 'n'

команда EXPLAIN показывает производную таблицу, которая не использует индекс и использует где и введите ALL

enter image description here

Это определение таблицы:

    -- SHOW CREATE TABLE locojourney
CREATE TABLE `locojourney` (
  `trainID` smallint(5) NOT NULL,
  `LocoNumber` varchar(5) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `CurrentLocoBase` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  `CurrentDuedate` date DEFAULT NULL,
  `LocoConsist` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `CurrentLocoDomain` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  `DomainChange` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `FEDR` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT 'N',
  `LADR` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT 'N',
  `ISBANKER` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT 'N',
  `TrainName` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `WithOutLoad` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'N',
  `runRoute` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `From_RunPoint` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `From_RunTime` datetime NOT NULL,
  `NEXT_RunPoint` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `NEXT_RunTime` datetime NOT NULL,
  `Affects_Outage` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT 'N',
  `Affects_Mileage` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT 'N',
  `GroundDistance` double(5,2) DEFAULT '0.00',
  `SHGallowance` int(11) DEFAULT '0',
  `Outage` double(5,4) DEFAULT '0.0000',
  `UnderServiceType` enum('FHT','CHG','DEP','MIX','DETN') CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'FHT',
  `SubServiceHead` varchar(25) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'RUN',
  `IShoc` enum('N','Y') CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT 'N',
  `CurrentCombiners` varchar(28) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  `RunSetSerla` varchar(25) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  `JourneySerla` int(11) NOT NULL AUTO_INCREMENT,
  `NominationSerla` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  `Traction` enum('DSL','AC') CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'DSL',
  `Trainload` smallint(4) NOT NULL DEFAULT '0',
  `LeadAssist` enum('Y','N') CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'N',
  `DEO` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  `DEOtime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`JourneySerla`),
  KEY `trainID` (`trainID`) USING BTREE,
  KEY `routesection_idx` (`runRoute`) USING BTREE,
  KEY `loconumber_idx` (`LocoNumber`) USING BTREE,
  KEY `runsetserla_idx` (`RunSetSerla`) USING BTREE,
  KEY `subservicehead_idx` (`SubServiceHead`) USING BTREE,
  CONSTRAINT `locojourney_ibfk_1` FOREIGN KEY (`SubServiceHead`) REFERENCES `ineffective` (`IneffectiveHead`) ON UPDATE CASCADE,
  CONSTRAINT `locojourney_ibfk_3` FOREIGN KEY (`runRoute`) REFERENCES `routesections` (`Sectionname`) ON DELETE RESTRICT ON UPDATE CASCADE,
  CONSTRAINT `loconumber_fk` FOREIGN KEY (`LocoNumber`) REFERENCES `lococontainer` (`LocoNumber`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=345719 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

Ответы [ 2 ]

0 голосов
/ 19 апреля 2019

Попробуйте:

SELECT  lj.CurrentCombiners , lj.JourneySerla , lj.From_RunPoint , lj.NEXT_RunPoint
    FROM (  SELECT  MAX(journeyserla) as lastrunid
                FROM  locojourney
                GROUP BY  loconumber 
         ) AS llr
    JOIN  locojourney AS lj  ON llr.lastrunid = lj.journeyserla
    WHERE  lj.ishoc = 'n' 

(рассчитайте время и предоставьте EXPLAIN)

0 голосов
/ 30 марта 2019
with LocomotiveLastRun AS(
       -- this block of code runs in 0.016 sec
    SELECT locojourney.loconumber , MAX(locojourney.journeyserla) as lastrunid
      FROM locojourney 
     GROUP BY loconumber)

Почему этот подзапрос CTE быстрый?Потому что ваша таблица уже имеет индекс на (loconumber, journeyserla).(InnoDb автоматически добавляет первичный ключ к каждому индексу.) Этот запрос может быть удовлетворен с помощью свободного сканирования индекса для этого индекса, и они выполняются быстро.

Теперь для вашего основного запроса:

  1. Избавиться от FORCE INDEX().Даже не мечтайте об этом, если у вас не было хотя бы десятилетнего опыта работы с SQL или вы не читали исходный код для индексации InnoDB в MySQL.Примечательно, что это совершенно бесполезно в CTE, потому что CTE не имеют индексов.
  2. Для ясности сначала поместите вашу основную таблицу (таблицу подробностей), а вторую - CTE.
  3. Для ясности измените JOIN какWHERE...IN...

Эти три предложения дают нам следующее:

   WITH LocomotiveLastRun AS (...)
 SELECT locojourney.CurrentCombiners , locojourney.JourneySerla , 
        locojourney.From_RunPoint , locojourney.NEXT_RunPoint 
   FROM locojourney
  WHERE journeyserla IN (SELECT lastrunid FROM LocomotiveLastRun)
    AND locojourney.ishoc = 'n'

Теперь ясно, какой индекс может помочь этому запросу.

Индекс на (ishoc) поможет немного.(Это на самом деле индекс, потому что InnoDB на (ishoc, journeyserla), поэтому он помогает с обоими условиями WHERE.) Планировщик запросов использует произвольный доступ BTREE для поиска первой строки индекса со значением ishoc 'n', а затем сканируетзначения первичного ключа для сопоставления их с предложением IN.

Вместо этого индекса составной индекс, который охватывает запроса, поможет еще больше.Такой индекс покрытия помогает особенно потому, что каждая строка вашей таблицы большая, со многими столбцами.В этом индексе упоминаются столбцы в предложении WHERE и те, которые вы хотите выбрать, например:

(ishoc, journeyserla, CurrentCombiners, From_RunPoint, NEXT_RunPoint)

Планировщик запросов может полностью удовлетворить ваш запрос из индекса, что экономит время чтения с диска, чтобы удовлетворитьзапрос.Если вы часто используете свой запрос, этот индекс - хорошая идея.Но он потребляет дисковое пространство и немного замедляет операции INSERT и UPDATE.

Чтение https://use -the-index-luke.com /

...