@mak_arti

Как написать запрос, который будет считывать меньше данных?

Таблица Crosses (ArticleId, CrossArticleId)
1 | 5
5 | 10
5 | 12
1 | 6
6 | 10
6 | 13
1 | 8
8 | 10
1 | 9
9 | 13
9 | 15

Строки ArticleId = 1 во временную таблицу @tempFlatCrosses (ArticleId, CrossArticleId)
1 | 5
1 | 6
1 | 8
1 | 9

Далее нужно сделать повторную выборку
select с.CrossArticleId from Crosses c
inner join @tempFlatCrosses f on c.ArticleId = f.CrossArticleId

То мы получим много дубликатов, будет считывать много лишних строк из таблицы Crosses.
10
12
10
13
10
13
15
Я понимаю что можно обойтись оператором Distinct, но все же хотелось чтобы запрос сканировал меньше данных из таблицы.
  • Вопрос задан
  • 84 просмотра
Пригласить эксперта
Ответы на вопрос 2
@Naiivi
Запрос можно оптимизировать тремя способами:
1) Использовать индексы по полям ArticleId и CrossArticleId в таблице Crosses;
2) Использовать группировку по полю CrossArticleId во временной таблице @tempFlatCrosses, чтобы избежать дубликатов при соединении с таблицей Crosses;
3) Использовать оператор EXISTS, вместо INNER JOIN, чтобы проверить наличие соответствующих записей в таблице Crosses, без возврата лишних данных.
-- Создаем индексы по полям ArticleId и CrossArticleId в таблице Crosses
CREATE INDEX idx_crosses_articleid ON Crosses (ArticleId);
CREATE INDEX idx_crosses_crossarticleid ON Crosses (CrossArticleId);

-- Достаем все строки, у которых ArticleId = 1 и группируем по CrossArticleId
SELECT ArticleId, CrossArticleId
INTO @tempFlatCrosses
FROM Crosses
WHERE ArticleId = 1
GROUP BY CrossArticleId;

-- Делаем выборку из таблицы Crosses, используя оператор EXISTS
SELECT c.ArticleId
FROM Crosses c
WHERE EXISTS (
  SELECT 1
  FROM @tempFlatCrosses f
  WHERE c.CrossArticleId = f.CrossArticleId
);
Ответ написан
@mvv-rus
Настоящий админ AD и ненастоящий программист
Здесь временная таблица не нужна: все можно сделать одним запросом:
select distinct c.CrossArticleId from Crosses c inner join Crosses f 
on c.ArticleId=f.CrossArticleId where f.ArticleId=1

А чтобы избежать сканирования всей таблицы, создайте (если их ещё нет)индексы по полям Crosses.ArticleId и Crosses.CrossArticleId - например, как в предыдущем ответе написано. И пусть работает и оптимизирует запрос планировщик: он кремниевый, и у него есть статистика по индексам. Если вдруг сомневаетесь в планировщике - посмотрите план выполнения запроса.
Индексы - это ключевой момент: без них серверу придется сканировать всю таблицу.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы