Есть ли разница между левым соединением и внутренним соединением относительно производительности? Я использую SQL Server 2012.Разница между левым соединением и внутренним соединением
ответ
Существует, по крайней мере, один случай, когда LEFT [OUTER] JOIN
является лучшим вариантом, чем [INNER] JOIN
. Я говорю о получении тех же результатов, используя OUTER
вместо INNER
.
Пример (я использую AdventureWorks 2008 database):
-- Some metadata infos
SELECT fk.is_not_trusted, fk.name
FROM sys.foreign_keys fk
WHERE fk.parent_object_id=object_id('Sales.SalesOrderDetail');
GO
CREATE VIEW View1
AS
SELECT h.OrderDate, d.SalesOrderDetailID, o.ModifiedDate
FROM Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
INNER JOIN Sales.SpecialOfferProduct o ON d.SpecialOfferID=o.SpecialOfferID AND d.ProductID=o.ProductID;
GO
CREATE VIEW View2
AS
SELECT h.OrderDate, d.SalesOrderDetailID, o.ModifiedDate
FROM Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
LEFT JOIN Sales.SpecialOfferProduct o ON d.SpecialOfferID=o.SpecialOfferID AND d.ProductID=o.ProductID;
GO
SELECT SalesOrderDetailID
FROM View1;
SELECT SalesOrderDetailID
FROM View2;
Результаты по первому запросу:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
планы выполнения двух последних запросов:
Примечание 1/Вид 1: Если мы посмотрим на план выполнения для SELECT SalesOrderDetailID FROM View1
мы видим FK elimination, потому что ограничение FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
доверено и имеет один столбец. Но сервер вынужден (из-за) читать данные из третьей таблицы (SpecialOfferProduct), даже предложения SELECT/WHERE
не содержат никаких столбцов из этой таблицы, а также ограничение FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) доверено. Это происходит потому, что последний FK является многоколоночным.
Примечание 2/View 2: Что делать, если мы хотим, чтобы удалить чтение (Scan
/Seek
) на Sales.SpecialOfferProduct
? Этот второй FK является многоколоночным, и для таких случаев SQL Server не может устранить FK (см. Предыдущую запись в блоге Conor Cunnigham). В этом случае нам необходимо заменить INNER JOIN Sales.SpecialOfferProduct
на LEFT OUTER JOIN Sales.SpecialOfferProduct
, чтобы получить исключение FK. Оба столбца SpecialOfferID
и ProductID
: NOT NULL
, и у нас есть доверенный FK, ссылающийся на таблицу SpecialOfferProduct
.
@MartinSmith: Я добавляю несколько заметок, но ** в этом случае ** они имеют одинаковую семантику. –
Они имеют одинаковую семантику, только если есть «FOREIGN KEY» из «SalesOrderDetail», ссылающегося на «SpecialOfferProduct». –
@ypercube: 'FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID' –
Так же как проблема, что внешнее соединение может вернуть больший результирующий набор из-за того, что дополнительные строки сохраняются, еще один момент заключается в том, что оптимизатор имеет больший диапазон возможностей при создании плана выполнения, поскольку INNER JOIN
является коммутативным и ассоциативным.
Таким образом, для следующего примера B
индексируется, но A
нет.
CREATE TABLE A(X INT, Filler CHAR(8000))
INSERT INTO A
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY @@SPID), ''
FROM sys.all_columns
CREATE TABLE B(X INT PRIMARY KEY, Filler CHAR(8000))
INSERT INTO B
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY @@SPID), ''
FROM sys.all_columns
SELECT *
FROM B INNER JOIN A ON A.X = B.X
SELECT *
FROM B LEFT JOIN A ON A.X = B.X
Оптимизатор знает, что B INNER JOIN A
и A INNER JOIN B
одинаковы и производит план с вложенными циклами ищет в таблице B
.
Это преобразование не является действительным для внешнего соединения и вложенность only supports left outer join not right outer join поэтому необходимо использовать другой тип соединения.
Но с практической точки зрения вам нужно просто выбрать тип соединения, в котором вы нуждаетесь, что даст вам правильную семантику.
- 1. Разница между левым соединением и левым внешним соединением
- 2. В чем разница между левым соединением и левым внешним соединением?
- 3. В чем разница между внутренним соединением и внутренним соединением? , HQL
- 4. Разница между левым соединением и правым соединением в SQL Server
- 5. Разница между внутренним соединением и левым соединением, если таблицы имеют совпадающие строки строк и первичные ключи
- 6. производительность разница между внутренним соединением, вложенным запросом и естественным соединением?
- 7. В чем разница между внутренним соединением и внешним соединением
- 8. разница между правым и внутренним соединением
- 9. Разница между внутренним соединением и столбцом Присоединиться
- 10. Разница между внутренним и внешним соединением
- 11. В чем разница между левым соединением (table1, table2) и левым соединением table1 left join table2
- 12. Запрос Sql, связанный с левым внутренним соединением или правым внутренним соединением?
- 13. В чем разница между левым внешним соединением и объединением?
- 14. В чем разница между объединением equi и внутренним соединением?
- 15. Есть ли разница между внутренним соединением и таблицей, разделенной запятой?
- 16. Разница между крестом и внутренним соединением основана на нижнем примере
- 17. Проблема с левым соединением
- 18. Застрял с левым соединением
- 19. Присоединиться к 4 таблицам в SQL с левым соединением и внутренним соединением
- 20. Обновление SQL внутренним соединением
- 21. DISTINCT с внутренним соединением
- 22. Выберите с внутренним соединением
- 23. Дубликаты с внутренним соединением
- 24. В чем разница между револьверным соединением и колёсным соединением
- 25. Разница между «естественным полным внешним соединением» и «полным внешним соединением»
- 26. Разница между Внутренним соединением VS Внутренний удаленный Присоединиться
- 27. Литиевое число с левым соединением
- 28. sql с левым соединением подзапроса
- 29. Разница между сеансом, HTTP-соединением?
- 30. SQL Server: как сделать запрос с левым внешним соединением + зависимым внутренним соединением?
Да, может быть разница. Но почему вас это волнует? Эти 2 не эквивалентны и будут (обычно) давать разные результаты. Итак, используйте тот, который полезен для вашего запроса и дает нужные вам результаты. –
Возможный дубликат [INNER JOIN vs LEFT JOIN performance в SQL Server] (http://stackoverflow.com/questions/2726657/inner-join-vs-left-join-performance-in-sql-server) –