#mysql #sql
Вопрос:
Это запрос, который никогда не заканчивается:
SELECT modelId, `timestamp` FROM thread_view WHERE id IN
(SELECT max(id) FROM thread_view
WHERE viewerId = 1 AND modelType = 'LEASE' AND modelId IN
(15,615,618,660) GROUP BY modelId);
Когда я запускаю только подзапрос, он завершается за 12 мс и возвращает два идентификатора. Когда я жестко кодирую эти 2 идентификатора вместо подзапроса, внешний запрос возвращает две строки и завершается за 0,3 мс.
Как вы можете видеть, обе части запроса выполняются невероятно быстро, и не похоже, что мы имеем дело с большим количеством данных. Когда я запускаю ОБЪЯСНЕНИЕ:
Объяснение не выявило у меня никаких проблем. Это просто ошибка с MySQL?
РЕДАКТИРОВАТЬ: mysql —версия дает: mysql версии 8.0.25 для macos11.3 на x86_64 (Доморощенный)
ПРАВКА №2: Как и было запрошено, вот инструкция create table:
CREATE TABLE `thread_view` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`timestamp` bigint DEFAULT NULL,
`viewerId` bigint DEFAULT NULL,
`modelType` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`modelId` bigint DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `viewerId_modelType_modelId` (`viewerId`,`modelType`,`modelId`)
) ENGINE=InnoDB AUTO_INCREMENT=50582 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
Комментарии:
1. Не могли бы вы обновить вопрос текстом
CREATE VIEW
заявления иCREATE TABLE
утверждениями (или другими), связанными с любыми базовыми объектами, к которым осуществляется доступVIEW
?2. Обратите
dependent subquery
внимание на план объяснения. Это часто является причиной проблем с производительностью. Это говорит о том, что либо ошибка, либо ваш SQL не является репрезентативным, либо у нас недостаточно подробностей в вопросе. Эти неквалифицированные ссылки на столбцы всегда должны разрешаться ближайшим объектом. В этом случае у вас есть один объект-представление. Таким образом, в SQL, который вы показали, действительно не должно быть никакого коррелированного / зависимого поведения. Может быть, в скрытомVIEW
определении есть что-то, что вызывает это. Трудно сказать без этой детали.3. извините, что это вводит в заблуждение, но thread_view на самом деле не является ПРЕДСТАВЛЕНИЕМ, это просто обычная таблица. Кроме того, это не «проблема с производительностью», запрос никогда не завершится, независимо от того, как долго он выполняется-и строк не так много.
4. ОК. Это прекрасно. Пожалуйста, покажите это определение (текст
CREATE TABLE
). Я не вижу никаких причин дляDEPENDENT
такого поведения. Вы уверены, что это «точный» SQL?5. @JonArmstrong Добавил!
Ответ №1:
Если цель действительно состоит в том, чтобы захватить наибольшую отметку времени для каждой модели (также отмечено @Shaharyar):
SELECT modelId
, MAX(`timestamp`)
FROM thread_view
WHERE modelId IN (15,615,618,660)
AND viewerId = 1
AND modelType = 'LEASE'
GROUP BY modelId
;
Ответ №2:
Я бы посоветовал вам вместо этого сформулировать это с помощью оконных функций. Я не уверен на 100%, что это эквивалентно (вы не объясняете данные или то, что должен делать ваш запрос).
Но если предположить, что id
это уникально, то попробуйте:
select t.*
from (select t.*,
row_number() over (partition by modelId order by id desc) as seqnum
from thread_view t
where viewerId = 1 and
modelType = 'LEASE' and
modelId in (15, 615, 618, 660)
) t
where seqnum = 1;
Комментарии:
1. Спасибо, Гордон, похоже, это дает тот же ответ, что и на мой вопрос, без замораживания. Цель этой таблицы-отслеживать, когда пользователи просматривают определенные страницы или модели, а затем быстро получать отметку времени, когда они в последний раз просматривали данный набор моделей.
2. @satnam если вы хотите получить
last timestamp
для каждой модели, почему бы не сделатьmax(timestamp)
это ? Вместо того, чтобы выбиратьid
первое, а затем выбиратьtimestamp
против этогоid
3. @Shaharyar интересная мысль, но я не совсем уверен, как это будет выглядеть-у вас есть пример запроса?
4.
SELECT modelId, MAX(`timestamp`) FROM thread_view WHERE modelId IN (15,615,618,660) AND viewerId = 1 AND modelType = 'LEASE' GROUP BY modelId;