2015-02-24 3 views
2

Мне интересно, почему MS SQL Server Query Planner создает вложенные циклы, а не выбирает Union для JOIN с условиями OR.ПРИСОЕДИНЯЙТЕСЬ с ИЛИ - Планировщиком запросов Выбор вложенных циклов

Примечание: Из поиска на SO, не кажется, MSSQL конкретные

Э.Г.

SELECT * FROM TableA a 
JOIN TableB b 
ON a.One = b.One 
OR a.Two = b.Two 

Принимает 6 минут в моем случае (И один и два индексируются на обеих таблицах)

Но

SELECT * FROM TableA a 
JOIN TableB b 
ON a.One = b.One 

UNION -- Not ALL, as need to remove duplicates 

SELECT * FROM TableA a 
JOIN TableB b 
ON a.Two = b.Two 

занимает 2 секунды.

Я знаю причину, по которой первое занимает так много времени (из-за вложенного цикла, где в качестве 2-х союзов используются индексы), но мне интересно, почему планировщик запросов не выбирает UNION в качестве плана выполнения?

Есть ли какое-то предостережение, о котором я должен знать при использовании UNION, для которого он не используется?

Почему эта логика не реализована в планировщике запросов?

Следует ли просто упростить код планировщика запросов (как его, вероятно, уже довольно сложный), что-то, что у них не было оптимизировано, или потому что есть некоторые другие оговорки, о которых я не знаю?

+0

@RhysJones очень правилен, иногда использование индексов замедляет вас из-за того, что при использовании некластеризованного индекса ему все равно придется искать кластерный индекс для данных. Так что здесь избирательность играет определенную роль. Другая проблема может быть более обыденной, но статистика может быть устаревшей. Когда последнее обновление статистики? – Namphibian

+1

Эти запросы не эквивалентны. Если 'TableA' или' TableB' содержат дубликаты своих * собственных *, первый запрос вернет их, второй запрос не будет. Оптимизатор не может переписать один на другой в целом. –

+2

@jeroen Это просто нужно использовать rid как дедупификатор, как это уже делается в некоторых случаях http://blogs.msdn.com/b/craigfr/archive/2006/08/30/732409.aspx –

ответ

0

Является ли это проблемой избирательности? SQL Server любит индексы быть очень избирательными. Один предикат всегда будет считаться более избирательным, чем два предиката OR'd, и разница в вашем случае может быть разницей между использованием индексов или нет.

См. SQL-журнал Барта Дункана Query Tuning Fundamentals: Density, Predicates, Selectivity, and Cardinality для длительной записи по избирательности.