У меня есть три таблицы:
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 управляют, таким образом, это не создало бы проблему), который сделает этот ключевой запрос еще быстрее.
SQL Boolean Оценка не может гарантировать оператор короткого замыкания. См. на коротко-цепи SQL Server Boolean Operator для четкого примера, показывающего, как предполагая короткое замыкание оператора может привести к тому, что проблемы правильности и ошибки выполнения.
С другой стороны, тот самый пример в моей ссылке показывает, что работает для SQL Server: предоставление пути доступа, которое может использовать SQL. Итак, как и с все Проблемы и вопросы и вопросы SQL, реальная проблема не так, как текст SQL выражен, но в дизайне вашего хранилища. Т.е. Какие индексы имеют оптимизатор запросов в его распоряжении, чтобы удовлетворить ваш запрос?
SQL Server обычно захватывает подсказку подзапрос (хотя это бесплатно отказаться от него):
SELECT *
FROM (
SELECT * FROM SmallTable where flag1 <> 1 or flag2 <> 1
) s
INNER JOIN JoinTable j ON j.SmallTableID = s.ID
...
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')
)
Это не элегантно, но должно работать...
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')
)
Я не верю, что SQL Server будет короткими условиями, к сожалению, к сожалению.
Итак, я предложил сделать 2 запроса и объединить их вместе. Первый запрос с S.FLAG1 = 1 и S.FLAG2 = 1, где условия, а второй запрос выполняет соединение на Bigtable с S.FLAG1 <> 1 A S.Flag2 <> 1 условия.
Это Статья по этому вопросу стоит прочитанного и включает в себя нижнюю строку:
... SQL Server не делает короткое замыкание, как это делается в другие языки программирования и Вы ничего не можете сделать, чтобы заставить его к.
Обновление:
Эта статья также является интересным чтением и содержит несколько хороших ссылок на эту тему, включая чат Technet с менеджером разработки для команды процессора запроса SQL Server, который кратко упоминает, что оптимизатор позволяет Оценка короткого замыкания. Общее впечатление, которое я получаю от различных статей: «Да, оптимизатор может обнаружить возможность короткого замыкания, но вы не должны полагаться на него, и вы не можете заставить его». Следовательно, я думаю, что профсоюзный подход может быть вашим лучшим ставкам. Если он не подходит с планом, который воспользуется возможностью для короткого вырезания, что было бы до оптимизатора на основе затрат, думая, что он нашел разумный план, который не делает это (это будет до индексов, статистики и т. Д.) Отказ