Соединения SQL, подзапросы вместо SQL (производительность)?



Я хочу знать, если у меня есть вступить запрос что-то вроде этого -



Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id


и подзапрос что-то вроде этого -



Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)


когда я считаю производительность какой из двух запросов будет быстрее и почему ?



также есть время, когда я должен предпочесть одну над другой?



Извините, если это слишком тривиально и спросил раньше, но я смущен об этом. Кроме того, это было бы здорово, если вы, ребята, можете предложить мне инструменты Я должен использовать для измерения производительности двух запросов. Большое спасибо!

780   8  

8 ответов:

Я ожидал бы, что первый запрос будет быстрее, главным образом потому, что у вас есть эквивалентность и явное соединение. По моему опыту IN - Это очень медленный оператор, так как SQL-запросы, как правило, оценивает его как серию WHERE предложения, разделенные "или" (WHERE x=Y OR x=Z OR...).

как и все вещи SQL, хотя, ваш пробег может отличаться. Скорость будет сильно зависеть от индексов (есть ли у вас индексы на обоих столбцах ID? Это очень поможет...) среди прочего.

единственный реальный способ чтобы сказать со 100% уверенностью, что быстрее, нужно включить отслеживание производительности (статистика ввода-вывода особенно полезна) и запустить их оба. Убедитесь в том, чтобы очистить кэш между запусками!

Ну, я считаю, что это" старый, но Золотой " вопрос. Ответ: "Это зависит!". Выступления-это такая тонкая тема, что было бы слишком глупо говорить: "никогда не используйте подзапросы, всегда присоединяйтесь". В следующих ссылках вы найдете некоторые основные рекомендации, которые я нашел очень полезными: здесь 1 здесь 2 здесь 3

у меня есть таблица с 50000 элементов, результат, который я искал, был 739 элементы.

мой запрос сначала был такой:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND p.anno = (
    SELECT MAX(p2.anno) 
    FROM prodotto p2 
    WHERE p2.fixedId = p.fixedId 
)

и это заняло 7,9 с, чтобы выполнить.

мой запрос наконец-это:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN
(
    SELECT p2.fixedId, MAX(p2.anno)
    FROM prodotto p2
    WHERE p.azienda_id = p2.azienda_id
    GROUP BY p2.fixedId
)

и это заняло 0.0256 s

хороший SQL, хорошо.

начните просматривать планы выполнения, чтобы увидеть различия в том, как SQl Server будет их интерпретировать. Вы также можете использовать Profiler для фактического выполнения запросов несколько раз и получить differnce.

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

часто лучше, чем любой из этих двух и когда вы говорите левые соединения, где вы хотите, чтобы все записи не были в левой таблице соединений, а затем не существовали, часто являются гораздо лучшим выбором.

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

Примечание дизайн эмпирическое правило, которое гласит, что таблица должна моделировать сущность/класс или отношения между сущностями / классами, но не оба. Поэтому, я предлагаю вам создать третью таблицу, скажем OrgChart, для моделирования отношений между сотрудниками и отделами.

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

Если это меньше данных вокруг 20k. JOIN работает лучше.

Если данные больше похожи на 100k+ , то в работает лучше.

Если вам не нужны данные из другой таблицы, в это хорошо, но это alwys лучше пойти на Существует.

все эти критерии я тестировал и таблицы имеют соответствующие индексы.

производительность должна быть одинаковой; гораздо важнее иметь правильные индексы и кластеризацию, применяемые к вашим таблицам (существует некоторые хорошие ресурсы на эту тему).

(отредактировано для отражения обновленного вопроса)

Я знаю, что это старый пост, но я думаю, что это очень важная тема, особенно в наши дни, когда у нас есть 10M+ записей и говорить о терабайтах данных.

Я также буду взвешивать следующие наблюдения. У меня есть около 45M записей в моей таблице ([данные]), и около 300 записей в моей таблице [кошки]. У меня есть обширная индексация для всех запросов, о которых я собираюсь говорить.

Рассмотрим Пример 1:

UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid

по сравнению с примером 2:

UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d

Пример 1 ушло около 23 минут. Пример 2 занял около 5 минут.

поэтому я бы сделал вывод, что подзапрос в этом случае намного быстрее. Конечно, имейте в виду, что я использую диски M. 2 SSD, способные к вводу/выводу @ 1GB/sec (это байты, а не биты), поэтому мои индексы тоже очень быстрые. Так что это может повлиять на скорость тоже в ваших обстоятельствах

если его одноразовая очистка данных, вероятно, лучше всего просто оставить его работать и закончить. Я использую TOP (10000) и см. сколько времени это займет и умножить на количество записей, прежде чем я попал в большой запрос.

Если вы оптимизируете производственные базы данных, я настоятельно рекомендую предварительно обрабатывать данные, т. е. использовать триггеры или брокер заданий для асинхронного обновления записей, чтобы доступ в реальном времени получал статические данные.

вы можете использовать план объяснения, чтобы получить объективный ответ.

для вашей проблемы, существует фильтр вероятно, будет выполнять самый быстрый.

Comments

    Ничего не найдено.