У меня есть таблица (MainTable
) с чуть более 600 000 записей. Он присоединяется на себя через 2 таблицы (JoinTable
) в отношениях типа родитель/ребенок:LEFT JOIN Значительно быстрее, чем INNER JOIN
SELECT Child.ID, Parent.ID
FROM MainTable
AS Child
JOIN JoinTable
ON Child.ID = JoinTable.ID
JOIN MainTable
AS Parent
ON Parent.ID = JoinTable.ParentID
AND Parent.SomeOtherData = Child.SomeOtherData
Я знаю, что каждый ребенок имеет запись родительской записи, и данные в JoinTable является Acurate.
Когда я запускаю этот запрос, требуется буквально несколько минут для запуска. Однако, если я присоединюсь к Родителю с помощью левого Присоединяйтесь тогда он принимает < 1 секунду для запуска:
SELECT Child.ID, Parent.ID
FROM MainTable
AS Child
JOIN JoinTable
ON Child.ID = JoinTable.ID
LEFT JOIN MainTable
AS Parent
ON Parent.ID = JoinTable.ParentID
AND Parent.SomeOtherData = Child.SomeOtherData
WHERE ...[some info to make sure we don't select parent records in the child dataset]...
Я понимаю разницу в результатах между INNER JOIN
и LEFT JOIN
. В этом случае он возвращает точно такой же результат, как и каждый ребенок имеет родителя. Если я позволю обоим запросам работать, я могу сравнить наборы данных, и они будут точно такими же.
Почему LEFT JOIN
работает намного быстрее, чем INNER JOIN
?
UPDATE Проверил планы запросов и при использовании внутреннего соединения начинается с Материнской набора данных. При выполнении левого соединения начинается с набора данных child.
Индексы, которые он использует, все одинаковы.
Могу ли я заставить его всегда начинать с ребенка? Использование левого соединения работает, он просто чувствует себя не так.
Подобные вопросы заданы здесь раньше, но никто, кажется, не отвечает на мой вопрос.
например. выбранный ответ в INNER JOIN vs LEFT JOIN performance in SQL Server говорит, что левые соединения всегда медленнее, чем внутренние. Аргумент имеет смысл, но это не то, что я вижу.
Проверьте планы. – Blorgbeard
@Blogbeard - см. Обновление – Greg