MySQL ПРИСОЕДИНЯЙТЕСЬ очень медленно без видимой причины - PullRequest
0 голосов
/ 28 марта 2020

MySQL версия 8.0.17:

SELECT b.ColB
FROM Table2 b
JOIN Table1 a ON a.ColA = b.ColA
WHERE b.ColB = 1234 -- some number

При JOIN выполнение этого запроса занимает около 2 секунд, без соединения это почти мгновенно. Это всего лишь минимальный пример, фактический случай требует, чтобы условие WHERE охватывало несколько значений (например, WHERE b.ColB BETWEEN 1000 AND 2000) - что занимает очень очень много времени ...

Структура таблицы 1 (нерелевантные столбцы и индексы удалены для краткости):

CREATE TABLE `Table1` (
  `ColA` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`ColA`)
) ENGINE=InnoDB AUTO_INCREMENT=138221783 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Структура таблицы 2 (нерелевантные столбцы и индексы удалены для краткости):

CREATE TABLE `Table2` (
  `ColA` int(11) NOT NULL,
  `ColB` int(11) NOT NULL,
  PRIMARY KEY (`ColA`,`ColB`),
  KEY `FK_Table2_Table1_idx` (`ColA`),
  KEY `FK_Table2_Table3_idx` (`ColB`),
  CONSTRAINT `FK_Table2_Table1` FOREIGN KEY (`ColA`) REFERENCES `Table1` (`ColA`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Это CSV объяснения по этому запросу:

id,select_type,table,partitions,type,possible_keys,key,key_len,ref,rows,filtered,Extra
1,SIMPLE,rc,NULL,ref,"PRIMARY,FK_Table2_Table1_idx,FK_Table2_Table3_idx",FK_Table2_Table3_idx,4,const,607,100.00,"Using index"
1,SIMPLE,r,NULL,eq_ref,PRIMARY,PRIMARY,4,Table2.ColA,1,100.00,"Using index"

Некоторая дополнительная информация, запускающая этот SELECT COUNT(*) FROM Table1, заняла 8,735 секунды и вернула 1947948.

Выполнение этого SELECT COUNT(*) FROM Table2 заняло 168,422 секунды и вернуло 19486319.

Почему JOIN что заставляет запрос выполняться очень медленно?

Ответы [ 2 ]

1 голос
/ 29 марта 2020

Если единственным индексом является PRIMARY KEY(colA, colB), а в предложении WHERE проверяется colB=constant, то пригодный для использования индекс отсутствует.

Если это таблица сопоставления «многие ко многим», вам необходимо добавьте INDEX(colB, colA) для эффективного перехода от B к A.

0 голосов
/ 28 марта 2020

Чтобы уменьшить количество строк, которые должны быть объединены, максимально уменьшите количество строк.

Для вашего qiery

Используйте

SELECT b.ColB
FROM (SELECT * FROM Table2 WHERE ColB = 1234) b
JOIN Table1 a ON a.ColA = b.ColA

Вместо SELECT * FROM Table2 вы должны использовать только тот столбец, который вам действительно нужен.

...