У меня есть таблица, показанная ниже
CREATE TABLE `xcpRush2_SandraTriplets` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`idConceptStart` int(11) NOT NULL,
`idConceptLink` int(11) NOT NULL,
`idConceptTarget` int(11) NOT NULL,
`flag` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_name` (`idConceptStart`,`idConceptLink`,`idConceptTarget`),
KEY `idConceptStart` (`idConceptStart`,`idConceptLink`,`idConceptTarget`),
KEY `idConceptStart_4` (`idConceptStart`),
KEY `idConceptTarget` (`idConceptTarget`),
KEY `idConceptLink` (`idConceptLink`,`idConceptTarget`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Данные будут выглядеть в скрипте db: https://www.db -fiddle.com / f / ejXP7qgvwNqAZeuaN3DFNz / 3
Как вы можете видеть, он полностью включен в несколько столбцов.
В моей таблице около 800k idConceptStart, удовлетворяющих условию
idConceptLink = 5 idConceptTarget = 14500 AND
idConceptLink = 3 idConceptLink = 14504 AND
idConceptLink = 12 idConceptLink = 11
Когда я выполняю этот запрос
SELECT * FROM xcpRush2_SandraTriplets l
JOIN xcpRush2_SandraTriplets link1 ON link1.idConceptStart = l.idConceptStart
JOIN xcpRush2_SandraTriplets link2 ON link2.idConceptStart = link1.idConceptStart
WHERE
l.idConceptLink = 5 AND
l.idConceptTarget = 14500 AND
l.flag != 1 AND
link2.flag != 1 AND
link2.idConceptLink = 3 AND
link2.idConceptTarget = 14504 AND
link1.flag != 1 AND
link1.idConceptTarget = 12 AND
l.idConceptLink = 11
ORDER BY l.idConceptStart DESC LIMIT 10
Вот SQL-объяснение
Запрос занимает около 30 секунд (!) Для визуализации
Но если я уберу это (итолько это)
link2.idConceptLink = 3 AND link2.idConceptTarget =14504
тогда запрос занимает 20 миллисекунд для визуализации
SELECT * FROM xcpRush2_SandraTriplets l
JOIN xcpRush2_SandraTriplets link1 ON link1.idConceptStart = l.idConceptStart
JOIN xcpRush2_SandraTriplets link2 ON link2.idConceptStart = l.idConceptStart
WHERE
l.idConceptLink = 5 AND
l.idConceptTarget = 14500 AND
l.flag != 1 AND
link2.flag != 1 AND
link1.flag != 1 AND
link1.idConceptTarget = 12 AND
link1.idConceptLink = 11
ORDER BY l.idConceptStart DESC LIMIT 10
Я озадачен, потому чтотаблица индексируется по idConceptLink
, idConceptTarget
, и каждый из этих запросов, взятых отдельно, очень быстро отображает <20 мс </p>
Кроме того, все пары idConceptLink
, idConceptTarget
в запросе возвращают тяжелыйколичество строк (не только link2.idConceptLink = 3 И link2.idConceptTarget = 14504)
Не могли бы вы помочь мне определить горлышко бутылки?
Редактировать
После дополнительных выводов в комментариях проблема, кажется, находится в ORDER BY.В зависимости от того, присоединяюсь ли я к l.idConceptStart или link1.idConceptStart или link2.idConceptStart, запрос выполняется медленно.В моем случае ORDER BY link2.idConceptStart работает медленно.
Структура индекса следующая:
CREATE TABLE `xcpRush2_SandraTriplets` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`idConceptStart` int(11) NOT NULL,
`idConceptLink` int(11) NOT NULL,
`idConceptTarget` int(11) NOT NULL,
`flag` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_name` (`idConceptStart`,`idConceptLink`,`idConceptTarget`),
KEY `idConceptStart` (`idConceptStart`),
KEY `idConceptTarget` (`idConceptTarget`),
KEY `idConceptLink` (`idConceptLink`,`idConceptTarget`)
) ENGINE=InnoDB AUTO_INCREMENT=5747878 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Индекс
xcprush2_sandratriplets 0 PRIMARY 1 id A 5207892 NULL NULL BTREE
xcprush2_sandratriplets 0 idx_name 1 idConceptStart A 1243366 NULL NULL BTREE
xcprush2_sandratriplets 0 idx_name 2 idConceptLink A 5207936 NULL NULL BTREE
xcprush2_sandratriplets 0 idx_name 3 idConceptTarget A 5207936 NULL NULL BTREE
xcprush2_sandratriplets 1 idConceptStart 1 idConceptStart A 1122352 NULL NULL BTREE
xcprush2_sandratriplets 1 idConceptTarget 1 idConceptTarget A 123870 NULL NULL BTREE
xcprush2_sandratriplets 1 idConceptLink 1 idConceptLink A 5 NULL NULL BTREE
xcprush2_sandratriplets 1 idConceptLink 2 idConceptTarget A 154480 NULL NULL BTREE
Запрос медленный , когда я делаю
SELECT l.idConceptStart, l.idConceptLink, l.`idConceptTarget` FROM xcpRush2_SandraTriplets l JOIN xcpRush2_SandraTriplets link1 ON link1.idConceptStart = l.idConceptStart JOIN xcpRush2_SandraTriplets link2 ON link2.idConceptStart = l.idConceptStart
WHERE l.idConceptLink = 5
AND l.idConceptTarget = 14500
AND l.flag != 1
AND link1.flag != 1 AND
link1.idConceptTarget =14504 AND link1.idConceptLink = 3 AND link2.flag != 1 AND
link2.idConceptTarget =12 AND link2.idConceptLink = 11 ORDER BY link2.idConceptStart DESC LIMIT 1000 OFFSET 0
Вот структура EXPLAIN
1 SIMPLE link1 NULL ref idx_name,idConceptStart,idConceptTarget,idConceptLink idConceptTarget 4 const 1611256 18.00 Using where; Using temporary; Using filesort
1 SIMPLE l NULL eq_ref idx_name,idConceptStart,idConceptTarget,idConceptLink idx_name 12 sandra.link1.idConceptStart,const,const 1 90.00 Using where
1 SIMPLE link2 NULL eq_ref idx_name,idConceptStart,idConceptTarget,idConceptLink idx_name 12 sandra.link1.idConceptStart,const,const 1 90.00 Using where
Запрос быстрый , когда я делаю
SELECT l.idConceptStart, l.idConceptLink, l.`idConceptTarget` FROM xcpRush2_SandraTriplets l JOIN xcpRush2_SandraTriplets link1 ON link1.idConceptStart = l.idConceptStart JOIN xcpRush2_SandraTriplets link2 ON link2.idConceptStart = l.idConceptStart
WHERE l.idConceptLink = 5
AND l.idConceptTarget = 14500
AND l.flag != 1
AND link1.flag != 1 AND
link1.idConceptTarget =14504 AND link1.idConceptLink = 3 AND link2.flag != 1 AND
link2.idConceptTarget =12 AND link2.idConceptLink = 11 ORDER BY l.idConceptStart DESC LIMIT 1000 OFFSET 0
Вот структура EXPLAIN
1 SIMPLE l NULL index idx_name,idConceptStart,idConceptTarget,idConceptLink idConceptStart 4 NULL 13036 3.08 Using where
1 SIMPLE link1 NULL eq_ref idx_name,idConceptStart,idConceptTarget,idConceptLink idx_name 12 sandra.l.idConceptStart,const,const 1 90.00 Using where
1 SIMPLE link2 NULL eq_ref idx_name,idConceptStart,idConceptTarget,idConceptLink idx_name 12 sandra.l.idConceptStart,const,const 1 90.00 Using where
Редактировать 2
оптимальная таблица для сортировки кажется случайной.Теперь, когда я выполнил тот же запрос несколько часов спустя (произошла некоторая вставка), но с использованием того же запроса изменилась структура решения порядка ключей.Быстрый запрос становится медленным, а медленный - быстрым.Если я ORDER BY l.idConceptStart, то следующее объяснение
порядок разрешения таблицы для ключей выглядит случайным.Я полностью потерян.В конце концов, единственное, что мне нужно, - это сначала получить последнюю запись в базе данных