이
오른쪽 사물의 영업 이익의 진술에 대응하기 위해 내가 안입니다 그것을 사용하고 싶다.
왜 는 JOIN
을 사용하지 않는 것일까? 예를 들어 ... 아주 글자 그대로 끔찍한 생각 서브 쿼리이다 사용의 마이크로 소프트에서 WideWorldImporters DATBASE에 아주 간단한 쿼리를 보자 :
SELECT I.InvoiceID,
O.OrderID,
O.OrderDate, O.ExpectedDeliveryDate
FROM sales.Invoices I
JOIN sales.Orders O ON I.OrderID = O.OrderID
WHERE I.InvoiceID BETWEEN 1 AND 1000;
를 통계 시간과의 IO, 이것은 결과 :
를
Table 'Orders'. Scan count 0, logical reads 3000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 4 ms, elapsed time = 4 ms.
약 예정입니다. 이제 하위 쿼리를 사용하여 메서드를 사용합시다 :
SELECT I.InvoiceID,
(SELECT O.OrderID FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderID,
(SELECT O.OrderDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderDate,
(SELECT O.ExpectedDeliveryDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS ExpectedDeliveryDate
FROM sales.Invoices I
WHERE I.InvoiceID BETWEEN 1 AND 1000;
그리고 비용은?
Table 'Orders'. Scan count 0, logical reads 9000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 10 ms, elapsed time = 10 ms.
글쎄, 놀랄는이 가 3000에서 9000으로,을 세 겹으로 읽지 않습니다! 또한 실행 시간이 두 배 이상입니다. 각 열에 대해 하위 쿼리를 사용했기 때문입니다.
PRINT 'Using JOIN';
SELECT I.InvoiceID,
C.CustomerName,
C.DeliveryPostalCode,
O.OrderID,
O.OrderDate, O.ExpectedDeliveryDate
FROM sales.Invoices I
JOIN sales.Orders O ON I.OrderID = O.OrderID
JOIN sales.Customers C ON O.CustomerID = C.CustomerID
WHERE I.InvoiceID BETWEEN 1 AND 1000;
PRINT 'Using Subqueries'
SELECT I.InvoiceID,
(SELECT C.Customername FROM sales.Customers C WHERE C.CustomerID = (SELECT O.CustomerID FROM sales.Orders O WHERE I.OrderID = O.OrderID)) AS CustomerName,
(SELECT C.DeliveryPostalCode FROM sales.Customers C WHERE C.CustomerID = (SELECT O.CustomerID FROM sales.Orders O WHERE I.OrderID = O.OrderID)) AS DeliveryPostalCode,
(SELECT O.OrderID FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderID,
(SELECT O.OrderDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderDate,
(SELECT O.ExpectedDeliveryDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS ExpectedDeliveryDate
FROM sales.Invoices I
WHERE I.InvoiceID BETWEEN 1 AND 1000;
결과 :
지금 바로 추가 점을 증명하기 위해, 우리는,이 어떻게되는지 "심하게"을 참조한다 고객 테이블에 가져 보자?
Using JOIN
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
(1000 rows affected)
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 1, logical reads 40, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 0, logical reads 3000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 9 ms, elapsed time = 8 ms.
Using Subqueries
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
(1000 rows affected)
Table 'Orders'. Scan count 0, logical reads 15000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 2000, logical reads 80000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 2028 ms, elapsed time = 2029 ms.
실행 시간을 살펴보십시오! 2 초 이상! JOIN
을 사용하여 동일한 쿼리를 수행하는 데 9ms가 걸렸습니다. 그리고 그 읽기를보세요!Orders 테이블의 15000 및 Customers 테이블의 80000 JOIN
을 사용하면 각각 3000과 40에 해당합니다.
그래서 다시 묻습니다. "왜 JOIN
을 사용하고 싶지 않으십니까?" 그렇게 할 이유가 없습니다. Keys와 인덱스가 없어도 성능은 기하 급수적으로 향상됩니다. 정직하게 당신이하는 일은 끔찍한 실수입니다. 하위 쿼리 사용에 대해 다시 생각해주십시오.
"** * NB : 나는 사용할 수 없습니다. ** **"물어보십시오. 왜? 별도로, 아니요, 하위 쿼리 (여러 행 또는 여러 열)에서 여러 값을 반환 할 수 없습니다. 그들은 단일 값을 리턴해야합니다. 'JOIN'을 사용하는 것이 여기에 대한 대답입니다. 내가 왜 당신을 사용하고 싶은지 아무 이유없이 생각할 수 없으며, 모든 ** 열에 하위 쿼리를 사용하면 끔찍한 성능이 나빠질 것입니다. 테이블은 각 열의 값에 대해 (적어도) 스캔해야합니다. – Larnu
옳은 일은 그것을 사용하고 싶지 않다는 것입니다. 나는 첫 번째 스타일로 지난 10 년 동안 많은 SQL 쿼리 작성을 리팩터링하려고합니다. 그리고 나는이 쿼리를 리팩토링하는 쉬운 방법을 찾는다. JOIN을 쓰지 않아도된다. 크로스, 인터 널, 내부 ...를 사용할 때 모든 외래 키를 검사 할 필요가있다. JOIN –
@JeanClaudeADIBA 작동한다면 변경하지 마라. . 나는 비추천 암시 적 조인을 좋아하지 않지만, 내가 그것을 발견 할 때 나는 엄격한 필요가없는 한 그것을 망치 려하지 않는다. C#, Delphi, VB, Java 등을 프로그래밍 할 수 있다면 semi-auto sql rewriter를 쉽게 만들 수 있습니다. 물론 동일한 스타일로 작성된 모든 수동 작업을 더 많이 수행해야합니다. – jean