2013-03-07 20 views
5

Tôi có truy vấn mất 2,5 giây với FULL JOIN và 40 giây với INNER, RIGHT hoặc LEFT JOIN.Làm thế nào để INNER/RIGHT/LEFT JOIN có thể chậm hơn 14 lần so với FULL JOIN?

Đây là truy vấn. Truy vấn phụ (thực hiện hai lần) chỉ mất 1,3 giây.

SELECT T1.[time], T1.Total, T1.rn, T2.[time], T2.Total, T2.rn 
FROM 
(
select [time], MAX(ComputedValue) as Total, row_number() over (order by [time]) as rn 
FROM 
(
    select SUBSTRING(CONVERT(CHAR(10), IntervalStartTime, 108), 0, 6) as [time], ComputedValue 
    from LoadTestTransactionSample 
    where LoadTestRunId=285 
    and CounterName='Total Transactions' 
    and TransactionName='Export' 
) foo 
group by [time] 
) T1 
_____ JOIN 
(
select [time], MAX(ComputedValue) as Total, row_number() over (order by [time]) as rn 
FROM 
(
    select SUBSTRING(CONVERT(CHAR(10), IntervalStartTime, 108), 0, 6) as [time], ComputedValue 
    from LoadTestTransactionSample 
    where LoadTestRunId=285 
    and CounterName='Total Transactions' 
    and TransactionName='Export' 
) foo 
group by [time] 
) T2 
ON T1.rn = T2.rn - 1 

bit select SUBSTRING chỉ nhận được chuỗi HH: MM ngoài giờ hẹn giờ. LoadTestTransactionSample thực sự là một VIEW tham gia trên 8 bảng. (FYI cơ sở dữ liệu là một cửa hàng kết quả kiểm tra tải Visual Studio). Dưới đây là các cột (có liên quan) của nó:

LoadTestRunId INT NOT NULL 
CounterName NVARCHAR(255) NOT NULL 
TransactionName NVARCHAR(64) NOT NULL 
IntervalStartTime DATETIME NOT NULL 
IntervalEndTime DATETIME NOT NULL 
ComputedValue REAL 

TÊN THAM GIA trả về một hàng không mong muốn, vì vậy tôi cần thực hiện RIGHT JOIN để có câu trả lời đúng.

Tôi không thực sự tìm kiếm một giải pháp (Tôi có một: tìm nạp trước subquery vào một bảng biến sử dụng SQL Server 2012 chức năng phân tích 'LAG', nhờ @ a1ex07), chỉ là một số hiểu biết như đến điều gì có thể gây ra sự khác biệt cực lớn về hiệu suất giữa các loại kết nối này.


EDIT: Đây là slow right join query planfast full join query plan. Chúng quá lớn để đăng ảnh chụp màn hình.

EDIT 2: Thực ra kế hoạch truy vấn có RIGHT JOIN ở mức 45% và FULL JOIN ở mức 55%, trong đó hóa ra là hoàn toàn không chính xác (trong thực tế nó kết thúc tồi tệ hơn 99%/1%). Tôi đoán điều này có nghĩa là tôi phải dựa vào số liệu thống kê thực hiện thực tế.

EDIT 3: Thống kê cho QUYỀN chậm THAM GIA:

(40 row(s) affected) 
Table 'LoadTestPerformanceCounterCategory'. Scan count 0, logical reads 37556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounter'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestScenario'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestCase'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'WebLoadTestTransaction'. Scan count 0, logical reads 13411100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterInstance'. Scan count 0, logical reads 36563718, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterSample'. Scan count 19721, logical reads 269657, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestRunInterval'. Scan count 41, logical reads 205, 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 = 36754 ms, elapsed time = 36763 ms. 

Thống kê cho nhanh FULL JOIN:

(41 row(s) affected) 
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 'LoadTestPerformanceCounterCategory'. Scan count 0, logical reads 1832, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounter'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestScenario'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestCase'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'WebLoadTestTransaction'. Scan count 0, logical reads 654200, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterInstance'. Scan count 0, logical reads 1783596, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterSample'. Scan count 962, logical reads 13154, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestRunInterval'. Scan count 2, logical reads 10, 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 = 1950 ms, elapsed time = 1944 ms. 

RIGHT JOIN đang làm ồ ạt nhiều lần đọc và quét hơn FULL JOIN, mặc dù có một kế hoạch truy vấn tương tự.

Có phải Bàn làm việc (trong FULL JOIN) một gợi ý? Đó có phải là một bảng tạm thời không?

Điều này có vẻ gợi ý rằng trình tối ưu hóa truy vấn bị hỏng không?

+1

Đặt thống kê kế hoạch truy vấn/hiển thị của bạn trên xem. Nếu không có các kịch bản lệnh DDL để có thể sao chép lược đồ và dữ liệu của bạn, thì bất kỳ câu trả lời nào về cơ bản đều là phỏng đoán. Ngoài ra, các số liệu hiệu suất này có khác nhau trên truy vấn đầu tiên như trên các truy vấn tiếp theo không? Đó là dấu hiệu cho thấy bộ nhớ cache của bạn đang tham gia. – Heather

+1

Tôi nghĩ rằng Heather có nghĩa là yêu cầu bạn chạy chúng 1-2-3-4 và sau đó 4-3-2-1 và so sánh –

+1

Ngoài ra, mỗi phiên bản của truy vấn sẽ tạo ra kế hoạch truy vấn của riêng nó trong bộ nhớ cache và chúng không nhất thiết làm mới cùng một lúc. Điều này có thể dẫn đến những câu hỏi về hiệu suất không thường xuyên. –

Trả lời

2

OK, hóa ra câu trả lời là: thống kê db xấu. Rất tệ. Như trong, không bao giờ được cập nhật.

exec sp_updatestats; FTW.

[ẩn đầu trong sự xấu hổ]

1

Đây là kế hoạch thực hiện cho các truy vấn tương tự. Bàn rất nhỏ.

Execution Plan

Query 1:

  • Sử dụng INNER JOIN.
  • Kế hoạch thực hiện trông nhỏ hơn.
  • Tuy nhiên, chiếm 62% tổng thời gian.

Query 2:

  • Sử dụng FULL JOIN.
  • Kế hoạch thực hiện có vẻ rất lớn.
  • Tuy nhiên, chiếm 38% tổng thời gian.

Lý do: INNER JOIN trong trường hợp của tôi đang sử dụng HASH MATCH. Và FULL JOIN đang sử dụng NESTED LOOP. Điều này được quyết định bởi trình tối ưu hóa SQL có thể sử dụng vật lý (tuy nhiên chúng ta có thể sử dụng phép nối vật lý khác). Kiểm tra kế hoạch thực hiện của bạn, nó sẽ giúp bạn.

+1

Bạn sẽ được hưởng lợi từ một số chỉ mục trên các bảng đó. – DaveShaw

+0

@DaveShaw: Đúng vậy. –

+0

@RaviSingh: kỳ lạ, có vẻ như các kế hoạch truy vấn không khớp với thực thi! Xem các chỉnh sửa của tôi - kế hoạch dự kiến ​​tỷ lệ 45%/55% cho RIGHT JOIN so với FULL JOIN, nhưng thực thi dẫn đến 99%/1%. – agentnega