Несколько запросов, чтобы избежать присоединений?

Я заметил, что как только я добавил присоединения к некоторым из моих запросов, время, затраченное на их выполнение, было больше, чем просто выполнение нескольких запросов.

Время включает загрузку страницы и в среднем более 20 загрузок страницы.

7-9 запросов без объединений
159 мс

3 запроса с 2 присоединениями
235 мс

Должен ли я просто использовать несколько запросов вместо объединений, учитывая, что они, похоже, оказывают такое значительное влияние на производительность? Я, вероятно, даже смогу оптимизировать метод множественных запросов, поскольку во время этих тестов я даже загружался лениво.

РЕДАКТИРОВАТЬ

Я создам ложную информацию ради вопроса.


ID объектов таблицы (int, идентификатор, PK, кластеризованный индекс)
UserID (int, некластеризованный индекс)
CategoryID (int, некластеризованный индекс)

Таблица
идентификаторов пользователей (int, идентификатор, PK, кластеризованный индекс)


Идентификатор категорий таблиц (int, идентификатор, PK, кластеризованный индекс)

Довольно просто. Это запрос двойного внутреннего соединения к таблице объектов. Запрос всех трех по отдельности кажется быстрее, чем соединение.

План запроса для объединения показывает, что 42% выполнено для 2 поисков по кластеризованному индексу, 23% - это сканирование кластерного индекса, а остальное - это сортировка Top N.

Ответов (6)

Решение

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

Первым шагом здесь должен быть анализ запроса. Я не очень хорошо знаком с вашим конкретным видом SQL, но, скорее всего, это будет что-то вроде EXPLAIN.

Если бы мне пришлось указать вероятного виновника, основываясь на той ограниченной информации, которую я имею здесь, мне бы не хватало индексов. Правильно ли проиндексированы поля, к которым вы присоединяетесь? Это может обеспечить ОГРОМНЫЙ прирост производительности. Во-вторых, вы присоединяетесь к нужным областям? Например, если вы объединяете две строки вместе, ваша производительность будет намного хуже, чем при объединении целочисленного или другого оптимизированного поля.

Я рекомендую вам взглянуть на фактический план запроса и понять, почему ответы различаются. Возможно, он выделит предложение сканирования таблицы, возможно, добавив индекс?

Объединение обходится дороже. Это не значит, что вы не должны их использовать.

Помогло бы увидеть SQL, который вы пишете ... (созданный LINQ to SQL)

если вы запускаете их только для получения данных в анализаторе запросов, тогда несколько запросов в порядке, но если вы запускаете их из веб-приложения или консольного приложения, вам нужно оптимизировать до 1 запроса. Даже если это займет немного больше времени, вы увидите прирост производительности, поскольку вы не обращаетесь к базе данных более одного раза. Чем меньше вы используете свой db, тем лучше будет производительность вашего интерфейса. Я буду работать над тем, чтобы ваши запросы были только одними. Похоже, что ваши таблицы нормализованы и достаточно проиндексированы, чтобы вы могли свести их к одному запросу.

Я бы постарался избавиться от всех типичных стыков. Например, я бы изменил:

select t1.id, t1.name, t2.gpa from t1 join t2 on t1.id =t2.id 

этим:

select t1.id, t1.name, t2.gpa from t1, t2 where t2.id = t1.id

Вы пробовали запускать запросы с объединениями через анализатор, чтобы узнать, что вы делаете для их оптимизации?

Нет, вам лучше пойти другим путем. Вам следует постараться получить как можно меньше запросов. Когда все сделано правильно, это самый быстрый.

Убедитесь, что у вас есть правильные индексы в таблице. Например, для такого запроса:

select a.Some, b.Other
from TableA a
inner join TableB b on b.Id = a.Id

Вы должны убедиться, что в поле TableB.Id есть индекс. Первичный ключ таблицы обычно получает индекс по умолчанию, но другие индексы вы должны создать самостоятельно.