Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Разлика в производителността между ляво и вътрешно съединение

Има поне един случай, при който LEFT [OUTER] JOIN е по-добра опция от [INNER] JOIN . Говоря за получаване на същите резултати с помощта на OUTER вместо INNER .

Пример (използвам база данни AdventureWorks 2008 ):

-- 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 елиминиране защото FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID ограничението е надеждно и има една колона. Но сървърът е принуден (поради INNER JOIN Sales.SpecialOfferProduct ), за да прочетете данни от третата таблица (SpecialOfferProduct) дори SELECT/WHERE клаузи не съдържа никакви колони от тази таблица и ограничението FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) е (също) надеждно. Това се случва, защото последният FK е многоколонен.

Бележка 2 / Изглед 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 таблица.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Синтаксис на заявка за актуализиране на SQL с вътрешно присъединяване

  2. unpivot с динамични колони плюс имена на колони

  3. Преобразуване с няколко бази - използване на всички комбинации за съкращаване на URL адреси

  4. Как да изберете определен брой символи отляво или отдясно на низ в SQL Server

  5. Проблем с SQL Server 2008 Intellisense