SQL WHERE для большой таблицы -> Сначала присоединиться к маленькой таблице или поместить FK непосредственно в предложение WHERE? - PullRequest
5 голосов
/ 21 декабря 2011

Что лучше в предложении WHERE?

У меня есть большой стол с FK на маленький стол.Я могу выполнить поиск по FK напрямую или присоединиться к таблице FK и установить ограничение WHERE для объединенной таблицы.Что лучше / предпочтительнее?

Так вот:

SELECT lt.* FROM LargeTable lt 
WHERE lt.SomeId in(12,55)

Или вот это:

SELECT lt.* FROM LargeTable lt 
INNER JOIN SmallTable st ON lt.SomeId=st.ItemId
WHERE st.Id in(12,55)

Я проверил это с Set statistics time on, но я не ожидал этого в результате.Кто может объяснить, что здесь происходит?

Первый тест без объединения:

(946 row(s) affected)
 SQL Server Execution Times:
   CPU time = 1544 ms,  elapsed time = 1580 ms.

Второй тест с объединением

(946 row(s) affected)
 SQL Server Execution Times:
   CPU time = 2636 ms,  elapsed time = 366 ms.

РЕДАКТИРОВАТЬ: Когда я делаю SELECT Id вместоравным SELECT *, тогда первый запрос без объединения имеет меньшее затраченное время, а стоимость запроса в плане выполнения составляет 25% для без объединения против 75% для запроса с объединением.

Ответы [ 3 ]

4 голосов
/ 21 декабря 2011

Исходя из ваших планов выполнения, оба запроса по сути сканируют каждую запись во всей большой таблице ... второй запрос просто находит небольшой набор записей из маленькой таблицы перед сканированием большой таблицы, поэтому относительный стоимость 50% для обоих.

Я бы порекомендовал рассмотреть индекс на largeTable.SomeId, а затем перейти к первому запросу:

SELECT lt.* FROM LargeTable lt 
WHERE lt.SomeId in(12,55)

EDIT:

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

Я думаю, что Мартин Смит дал ответ на этот вопрос:

Ваш второй получает параллельный план, а первый нет

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

0 голосов
/ 21 декабря 2011
  1. Поскольку оба запроса извлекают результаты из большой таблицы, как уже упоминалось.Итак, у вас есть Некластеризованный индекс для столбца "SomeID"?

  2. Используете ли вы все столбцыиз этой таблицы.Если это не так.Рекомендуется указывать только обязательные столбцы.

  3. Поскольку оба запроса извлекают данные из большой таблицы, то это можно сделать только из первого запроса с " Non Clustered Index "

  4. Если есть какой-либо случай, чтобы получить только совпадающие данные.Тогда вы можете сделать, как показано ниже:

    Select ColumnName From
    (
     Select ColumnName, SomeID from LargeTable Where SomeID in(12,13)
    )T
    Inner Join SmallTable T1 on T.SomeID = T1.SomeID
    
  5. Если вы хотите очень быстрые результаты.Вы можете сделать, как показано ниже.

    Create table #Large
    (
      Id Int,
      ColumnName Varchar(100)
    )
    Insert into #Large(ID, ColumnNmae)
    Select ColumnName, SomeID from LargeTable Where SomeID in(12,13)
    

И, наконец, с объединением

Select ColumnName From #Large T
Inner Join SmallTable T1 on T.SomeID = T1.SomeID

и без объединения

Select ColumnName from #Large
0 голосов
/ 21 декабря 2011

2 вещи для рассмотрения:

  1. Ваше внутреннее объединение вернуло меньший набор данных?в этом случае ваше условие where выполняется на меньшем количестве строк.
  2. Я думаю, что во втором запросе вы хотели сказать где st.Id в (12, 55) , и в этом случае ваше предложение where работает с индексом первичного ключа, который кластеризовани, следовательно, намного быстрее, чем ваш некластерный индекс внешнего ключа
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...