T-SQL: необязательные объединения таблиц? - PullRequest
6 голосов
/ 08 ноября 2011

Допустим, у меня есть хранимая процедура, которая будет выполнять сложную логику, когда параметр @ComplicatedSearch = 1.Когда он установлен в 1, я заполняю таблицу переменных @ValidIds допустимыми строками, которые эта процедура может вернуть.Когда он равен 0, логика обойдена, и нам не нужно отфильтровывать строки для возврата.

Итак, после этой логики я получаю следующее утверждение:1007 * Это отлично работает;однако я считаю, что было бы более эффективно объединить MyTable с @ValidIds, когда это применимо, а не с использованием EXISTS(), особенно когда MyTable содержит большое количество строк.есть ниже без написания нескольких запросов?(фактический запрос очень большой, поэтому наличие нескольких версий с объединениями и без них не будет идеальным)

SELECT
    m.*
    ,a.*
FROM
    MyTable m
    ONLY DO THIS IF ComplicatedSearch = 1 PLEASE: INNER JOIN @ValidIds v
       ON m.Id = v.Id
    INNER JOIN AdditionalInfoTable a
       ON m.Id = a.MyTableId

Ответы [ 2 ]

6 голосов
/ 08 ноября 2011

Другой вариант:

SELECT
   m.*     
  ,a.*
FROM MyTable m    
 INNER JOIN @ValidIds v
  ON m.Id = case
              when @ComplicatedSearch = 1 then v.Id  --  Filter rows
              else m.Id  --  Select all rows
            end
 INNER JOIN AdditionalInfoTable a    
  ON m.Id = a.MyTableId

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

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

5 голосов
/ 08 ноября 2011

Если вы стремитесь к эффективности, вы должны заметить, что хранимые процедуры рассчитают план запроса при первом запуске, затем кешируют его и затем используют тот же.В этом случае это означает, что он выберет использование @ValidIds в зависимости от первого значения @ ComplicatedSearch

Таким образом, я бы написал процедуру более похожую на

if @ComplicatedSearch = 1
   exec simple_search
else
   exec complex_search

Где simple_search включает ваш первый запроси complex_search также присоединяется к @ ValidIds

Если вы получаете запрос дважды, но для этого я бы создал представление

create view helper as
begin
SELECT
    m.*
    ,a.*
FROM
    MyTable m
    INNER JOIN AdditionalInfoTable a
       ON m.Id = a.MyTableId
end

, а затем просто выбираю из этого представления и сложные соединения присоединяются к @ValidIds

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...