Как оптимизировать выбор MySQL со строками, не имеющими совпадающих значений в другой таблице - PullRequest
1 голос
/ 19 июня 2020

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

В этой таблице ~ 120 000 строк.

CREATE TABLE `tblTimers` (
  `TimerID` int(11) NOT NULL,
  `TaskID` int(11) NOT NULL,
  `UserID` int(11) NOT NULL,
  `StartDateTime` datetime NOT NULL,
  `dtStopTime` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `tblTimers`
  ADD PRIMARY KEY (`TimerID`);
ALTER TABLE `tblTimers`
  MODIFY `TimerID` int(11) NOT NULL AUTO_INCREMENT;

В этой таблице около 70 000 строк.

CREATE TABLE `tblWorkDays` (
  `WorkDayID` int(11) NOT NULL,
  `TaskID` int(11) NOT NULL,
  `UserID` int(11) NOT NULL,
  `WorkDayDate` date NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `tblWorkDays`
  ADD PRIMARY KEY (`WorkDayID`);

ALTER TABLE `tblWorkDays`
  MODIFY `WorkDayID` int(11) NOT NULL AUTO_INCREMENT;

tblWorkDays должен иметь одну строку на TaskID на UserID на WorkDayDate, но из-за ошибки не хватает нескольких рабочих дней несмотря на то, что на те дни были таймеры; Итак, я пытаюсь создать отчет, который показывает любой таймер, с которым не связан рабочий день.

SELECT A.TimerID FROM tblTimers A
LEFT JOIN tblWorkDays B ON A.TaskID = B.TaskID AND A.UserID = B.UserID AND DATE(A.StartDateTime) = B.WorkDayDate
WHERE B.WorkDayID IS NULL

Это приводит к тайм-ауту сервера; Итак, я ищу, есть ли способ сделать это более эффективно?

1 Ответ

2 голосов
/ 19 июня 2020

У вас нет индексов для столбцов, к которым вы присоединяетесь, поэтому он должен выполнить полное сканирование обеих таблиц. Попробуйте добавить следующее:

ALTER TABLE tblTimers ADD INDEX (TaskID, UserID);
ALTER TABLE tblWorkDays ADD INDEX (TaskID, UserID);
...