Ярлык выполнения SQL-запроса ИЛИ логика?

У меня есть три таблицы:

SmallTable
   (id int, flag1 bit, flag2 bit)
JoinTable
   (SmallTableID int, BigTableID int)
BigTable
   (id int, text1 nvarchar(100), otherstuff...)

SmallTable имеет, самое большее, несколько дюжин записей. BigTable имеет несколько миллионов и на самом деле представление что ОБЪЕДИНЕНИЯ таблица в этой базе данных с таблицей в другой базе данных по тому же серверу.

Вот логика соединения:

SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=1 OR b.text1 NOT LIKE 'pattern1%')
    AND (s.flag2=1 OR b.text1 <> 'value1')

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

Для большинства SmallTable записи, flag1 и flag2 установлены на 1, таким образом, нет действительно никакой потребности к, даже получают доступ к индексу на BigTable.text1, но SQL Server делает так или иначе, ведя на дорогостоящее Индексируемое Сканирование и Вложенный цикл.

Есть ли лучший способ подсказать SQL Server это, если flag1 и flag2 оба установлены на 1, это не должно даже потрудиться смотреть на text1?

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

7
задан bluish 27 June 2012 в 09:29
поделиться

5 ответов

SQL Boolean Оценка не может гарантировать оператор короткого замыкания. См. на коротко-цепи SQL Server Boolean Operator для четкого примера, показывающего, как предполагая короткое замыкание оператора может привести к тому, что проблемы правильности и ошибки выполнения.

С другой стороны, тот самый пример в моей ссылке показывает, что работает для SQL Server: предоставление пути доступа, которое может использовать SQL. Итак, как и с все Проблемы и вопросы и вопросы SQL, реальная проблема не так, как текст SQL выражен, но в дизайне вашего хранилища. Т.е. Какие индексы имеют оптимизатор запросов в его распоряжении, чтобы удовлетворить ваш запрос?

5
ответ дан 7 December 2019 в 10:02
поделиться

SQL Server обычно захватывает подсказку подзапрос (хотя это бесплатно отказаться от него):

SELECT      * 
FROM        (
            SELECT * FROM SmallTable where flag1 <> 1 or flag2 <> 1
            ) s
INNER JOIN  JoinTable j ON j.SmallTableID = s.ID
...
0
ответ дан 7 December 2019 в 10:02
поделиться

No idea if it will be faster without test data. ... но похоже, что это может

SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=1) AND (s.flag2=1)
 UNION ALL
 SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=0 AND b.text1 NOT LIKE 'pattern1%')
    AND (s.flag2=0 AND b.text1 <> 'value1')

Пожалуйста, дайте мне знать, что произойдет

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

редактировать

что-то вроде этого?

SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=1) AND (s.flag2=1)
 UNION ALL
 SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE EXISTS
    (SELECT 1 from BigTable b
     WHERE   
    (s.flag1=0 AND b.text1 NOT LIKE 'pattern1%')
    AND (s.flag2=0 AND b.text1 <> 'value1')
)
0
ответ дан 7 December 2019 в 10:02
поделиться

Это не элегантно, но должно работать...

SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1 = 1 and s.flag2 = 1) OR 
    (
       (s.flag1=1 OR b.text1 NOT LIKE 'pattern1%')
       AND (s.flag2=1 OR b.text1 <> 'value1')
    )
0
ответ дан 7 December 2019 в 10:02
поделиться

Я не верю, что SQL Server будет короткими условиями, к сожалению, к сожалению.

Итак, я предложил сделать 2 запроса и объединить их вместе. Первый запрос с S.FLAG1 = 1 и S.FLAG2 = 1, где условия, а второй запрос выполняет соединение на Bigtable с S.FLAG1 <> 1 A S.Flag2 <> 1 условия.

Это Статья по этому вопросу стоит прочитанного и включает в себя нижнюю строку:

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

Обновление:
Эта статья также является интересным чтением и содержит несколько хороших ссылок на эту тему, включая чат Technet с менеджером разработки для команды процессора запроса SQL Server, который кратко упоминает, что оптимизатор позволяет Оценка короткого замыкания. Общее впечатление, которое я получаю от различных статей: «Да, оптимизатор может обнаружить возможность короткого замыкания, но вы не должны полагаться на него, и вы не можете заставить его». Следовательно, я думаю, что профсоюзный подход может быть вашим лучшим ставкам. Если он не подходит с планом, который воспользуется возможностью для короткого вырезания, что было бы до оптимизатора на основе затрат, думая, что он нашел разумный план, который не делает это (это будет до индексов, статистики и т. Д.) Отказ

1
ответ дан 7 December 2019 в 10:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: