#sql #sql-server #tsql #sql-server-2014
#sql #sql-сервер #tsql #sql-server-2014
Вопрос:
У меня есть две таблицы SQL, Countries и CountriesI18N:
Countries > Code
CountriesI18N > CountryCode, LanguageCode, Name
Я получаю список стран, выбирающих следующее:
- Код стран.
- Название стран18, которым задан язык.
Первый вариант T-SQL следующий:
SELECT [x].[Code], (
SELECT TOP(1) [z].[Name]
FROM [CountriesI18N] AS [z]
WHERE ([z].[LanguageCode] = 'en' AND ([x].[Code] = [z].[CountryCode])
) AS [Name]
FROM [Countries] AS [x]
И и альтернатива с использованием внутреннего соединения:
SELECT [x].[Code], [x.CountriesI18N].[Name]
FROM [Countries] AS [x]
INNER JOIN [CountriesI18N] ON [x].[Code] = [x.CountriesI18N].[CountryCode]
WHERE [x.CountriesI18N].[LanguageCode] = 'en'
Эквивалентны ли они с точки зрения скорости и эффективности?
Если бы у меня было много связанных таблиц, использование многих внутренних соединений или подзапросов было бы эквивалентно?
Комментарии:
1. Откройте SSMS. Пресса
<ctrl> N
. В новом окне запроса вставьте оба запроса. Пресса<ctrl> M
. Запустите запросы. Проверьте план выполнения. Гоните своих лошадей.2. «дочерний запрос» = подзапрос 🙂
3. Краткий ответ на это:
it depends
. Размеры таблиц, индексы, фрагментация, типы данных, даже количество столбцов в таблице — все это оказывает влияние. Обычно , если вы можете записать это какJOIN
, вам, вероятно, следует; оптимизатор лучше всего знаком с этим, людям легче читать и поддерживать и т.д. и т.п. Но какой из них использует больше ресурсов и который быстрее (Это не одно и то же; однопоточный план может занимать больше времени и в то же время использовать меньше ресурсов, чем многопоточный план) лучше всего измеряется с помощью профилировщика SQL Server и / или просмотра планов выполнения.4. Кроме того, ваши запросы не совпадают. Первое гарантирует одно имя для каждого кода. Второй вариант допускает возможность использования нескольких имен в коде. То, что они могут генерировать разные результаты, скорее всего, означает, что они генерируют разные планы выполнения. Тем больше причин для проверки планов выполнения, чтобы увидеть, насколько они отличаются, и использования профилировщика для точного измерения использования ресурсов.
5. @MatBailie Как бы мне изменить второй запрос, чтобы получить только одно имя? На самом деле при локализации по странам у меня есть уникальное ограничение на <Код страны, код языка>, потому что это PK. Итак, я знаю, что для каждого языкового кода я получу только одно имя.
Ответ №1:
Во-первых, они не являются эквивалентными запросами. Для ваших конкретных данных они могут выглядеть эквивалентными, но это не так. Подзапрос возвращает соответствие с точностью до одного. inner join
Отфильтровывает несоответствия и может возвращать дубликаты.
Итак, вы сравниваете яблоки и апельсины.
В любом случае вам нужен индекс на CountriesI18N(CountryCode, LanguageCode)
. Так получилось, что это наилучший индекс для обеих версий запроса.
Комментарии:
1. (Код страны, код языка) уже является PK для CountriesI18N в качестве составного ключа … Итак, это покрывает это, верно?
2. Да, я знаю, что это не одно и то же… Я попробую сделать внутреннее соединение похожим на подзапрос для сравнения в аналогичных условиях