Các Cơ Chế Thực Thi Lệnh JOIN Tiếp theo bài Các Loại JOIN Trong SQL Server, bài này
lượt xem 21
download
Các Cơ Chế Thực Thi Lệnh JOIN Tiếp theo bài Các Loại JOIN Trong SQL Server, bài này giới thiệu về các cơ chế bên trong SQL Server sử dụng để xử lý các câu truy vấn JOIN. Về cơ bản khi thực hiện câu lệnh JOIN, SQL Server duyệt qua hai bảng tham gia vào, lấy ra từng cặp bản ghi để so sánh, rồi trả về tập kết quả nếu thỏa mãn điều kiện JOIN hoặc loại bỏ nếu không thỏa mãn.
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: Các Cơ Chế Thực Thi Lệnh JOIN Tiếp theo bài Các Loại JOIN Trong SQL Server, bài này
- Các Cơ Chế Thực Thi Lệnh JOIN Tiếp theo bài Các Loại JOIN Trong SQL Server, bài này giới thiệu về các cơ chế bên trong SQL Server sử dụng để xử lý các câu truy vấn JOIN. Về cơ bản khi thực hiện câu lệnh JOIN, SQL Server duyệt qua hai bảng tham gia vào, lấy ra từng cặp bản ghi để so sánh, rồi trả về tập kết quả nếu thỏa mãn điều kiện JOIN hoặc loại bỏ nếu không thỏa mãn. SQL Server cài đặt một vài thuật toán khác nhau , thích hợp với các tình huống khác nhau (như số lượng bản ghi cần so sánh nhiều hay ít, cột JOIN có index hay không…). Các thuật toán đó là Nested Loop Join, Merge Join, và Hash Join. Nested Loop Join Đây là thuật toán rất đơn giản và cũng rất hiệu quả đ ối với tập dữ liệu nhỏ, nó lấy mỗi bản ghi trong một bảng (gọi là inner table) và so sánh với từng bản ghi của bảng kia (gọi là outer table) để tìm ra bản ghi thỏa mãn. Thuật toán này có thể được viết ở dạng pseodo-code như sau: Code: for each row R1 in the outer table for each row R2 in the inner table if R1.join_column = R2.join_column return (R1, R2) *copy từ Craig Freedman’s Blog) Ví dụ 1: Code: USE AdventureWorkds GO SELECT a.SalesOrderDetailID, b.Name FROM Sales.SalesOrderDetail a JOIN Production.Product b ON a.ProductID = b.ProductID W HERE a.SalesOrderID = 43659 Trong phương án thực thi ở hình trên, bạn thấy hai thao tác Clustered index seek,
- bảng ở thao tác trên luôn luôn là outer table, và bảng dưới luôn là inner table. Vì số bản ghi được trả về là nhỏ, bộ Optimizer đã chọn Nested Loop Join. Nói chung Nested Loop Join thích hợp khi outer table có số bản ghi nhỏ và inner table đã được sắp xếp theo trường được JOIN (ví dụ trường này có clustered index). Khi đó, việc quét bảng inner table (vòng lặp trong) trở thành index seek. Khi xây dựng phương án thực thi, bộ Optimizer sẽ tự động chọn một bảng làm outer table và bảng kia làm inner table theo cách để đảm bảo chi phí là nhỏ nhất. Nested Loop Join là thao tác join bạn mong đợi xuất hiện nhất trong phương án thực thi, vì nó chứng tỏ câu truy vấn được thực hiện hiệu quả và có chi phí thấp. Khi số bản ghi tăng lên hoặc bảng inner table không được sắp thứ tự (vì không có index hỗ trợ), bộ Optimizer sẽ xem xét đến Merge Join hoặc Hash Join, vì lúc đó các thuật toán này có thể sẽ hiệu quả hơn so với Nested Loop Join. Cần phân biệt các thuật toán kể trên với các loại JOIN mà bạn dùng khi viết cod e như INNER JOIN, OUTER JOIN. Theo thuật ngữ của Microsoft, các loại JOIN đó được gọi là logical operator (các toán tử ở mức logic); còn các thuật toán trên gọi là physical operator (các toán tử ở mức vật lý). Khi viết code, bạn dùng các toán tử mức logic để diễn đạt yêu cầu, hệ thống sẽ xem xét và sử dụng một toán tử mức vật lý (một trong ba thuật toán) thích hợp để thực thi câu lệnh. Merge Join Kỹ thuật này đòi hỏi hai bảng phải cùng được sắp xếp theo thứ tự của trường JOIN. Nó đọc từng cặp bản ghi của mỗi bảng và so sánh với nhau. Nếu khớp thì gửi ra tập kết quả. Nếu không thì nó loại bản ghi có trường JOIN nhỏ hơn, đọc tới bản ghi tiếp theo của bảng tương ứng và tiếp tục quá trình. Với thuật toán này, hai bảng được đọc từ đầu và cùng tiến lên song song với nhau. Pseodo-code của thuật toán Merge Join như sau: Code: get first row R1 from table 1 get first row R2 from table 2 while not at the end of either table begin if R1.join_column = R2.join_column begin return (R1, R2) get next row R2 from table 2 end else if R1.join_column < R2.join_column get next row R1 from table 1 else get next row R2 from table 2 end (*copy từ Craig Freedman’s Blog) Ví dụ 2: Cùng câu truy vấn như ở phần trước, nhưng bỏ qua mệnh đề WHERE Code:
- SELECT a.SalesOrderDetailID, b.Name FROM Sales.SalesOrderDetail a JOIN Production.Product b ON a.ProductID = b.ProductID --WHERE a.SalesOrderID = 43659 Với câu lệnh trên thì Merge Join trở nên thích hợp, vì số bản ghi trả về là lớn và cả hai bảng đều đã được sắp xếp (nói chính xác ra là, đối với bảng SalesOrderDetail nó chỉ cần đọc index trên trường ProductID, và tất nhiên index đã sắp xếp sẵn). Số phép so sánh, và do đó, chi phí của thuật toán này, tương đương với tổng của số bản ghi trong hai bảng. Do đó thuật toán này hoạt động hiệu quả hơn Nested Loop khi số bản ghi tăng cao. Trong nhiều trường hợp, thuật toán kết thúc khi nó mới chỉ quét xong bảng nhỏ hơn, vì bảng kia nếu có quét tiếp cũng không tìm được bản ghi nào thỏa mãn nữa. Khi đó số lần so sánh chỉ bằng hai lần số bản ghi của bảng nhỏ. Nếu một trong hai bảng không được sắp sẵn thứ tự, bộ Optimizer có hai lựa chọn: (1) sắp xếp lại bảng theo thứ tự trường JOIN rồi áp dụng Merge Join hoặc (2) chuyển sang dùng Hash Join. Phương án nào rẻ hơn sẽ được chọn. Hash Join Thuật toán này phát huy hiệu quả nhất đối với lượng dữ liệu lớn và không được sắp xếp sẵn. Nó được thực hiện làm hai giai đoạn: xây dựng (build) và dò tìm (probe). Ở bước xây dựng, nó quét qua một bảng (gọi là build table), và băm (hash) các bản ghi dựa vào trường JOIN, rồi xây dựng một bảng băm (hash table) trong bộ nhớ. Đến bước dò tìm, nó đọc bảng thứ hai (gọi là probe table) và cũng băm các bản ghi dùng trường JOIN, rồi dùng giá trị băm đó để tìm trên bảng băm. Mỗi lần tìm được nó gửi cặp bản ghi tương ứng ra tập kết quả. Pseodo -code: Code: for each row R1 in the build table begin calculate hash value on R1.join_column insert R1 into the appropriate hash bucket
- end for each row R2 in the probe table begin calculate hash value on R2.join_column for each row R1 in the corresponding hash bucket if R1.join_column = R2. join_column return (R1, R2) end (*copy từ Craig Freedman’s Blog) Ví dụ 3: giống như ví dụ 2 nhưng thêm một trường OrderQty vào phần SELECT Code: SELECT a.SalesOrderDetailID, a.OrderQty, b.Name FROM Sales.SalesOrderDetail a JOIN Production.Product b ON a.ProductID = b.ProductID --WHERE a.SalesOrderID = 43659 Ở ví dụ này Hash Join đã được sử dụng, mặc dù số bản ghi được trả về giống như ở ví dụ 2. Lưu ý ở ví dụ 2, bảng SalesOrderDetail chỉ cần đọc index trên trường ProductID là đủ, và vì input cho việc join đã được sắp xêp nên Merge Join đã được dùng. Nhưng ở ví dụ 3, vì có thêm trường OrderQty nên chỉ đọc index trên trường ProductID là không đủ mà hệ thống phải đọc cả vào bảng nữa. Input cho thao tác join lúc này không còn được sắp xếp nữa và do đó, Hash Join trở nên thích hợp hơn. Trong các tình huống như thế này Hash Join có ưu thế hơn Merge Join vì việc xây dựng bảng băm nhanh hơn sắp xếp lại bảng, hơn nữa nó chỉ cần áp dụng đối với một bảng. Thông thường bộ Optimizer chọn bảng nhỏ để xây dựng bảng băm để không cần chiếm quá nhiều bộ nhớ. Tuy vậy so với Nested Loop Join và Merge Join thì thuật toán này đòi hỏi rất nhiều tài nguyên CPU và bộ nhớ. Khi Hash Join xuất hiện trong phương án thực thi, đó là chỉ dấu cho thấy lượng dữ liệu cần xử lý khá lớn (do không có mệnh đề WHERE, chủ ý hoặc do quên không đưa vào) và không có index
- hỗ trợ. Trong các hệ thống OLTP, vốn đặc trưng bởi nhiều giao dịch được thực hiện nhanh, Hash Join cho thấy nhiều khả năng là câu lệnh chưa được thực hiện tối ưu. Còn trong môi trường data warehouse, các thao tác xử lý thường trên một lượng dữ liệu lớn, do đó Hash Join được sử dụng rất thường xuyên. Lời kết Trên đây giới thiệu các thuật toán SQL Server dùng để thực thi câu lệnh JOIN. Trên thực tế các thuật toán phức tạp hơn và còn có nhiều biến thể để bộ Optimizer tinh chỉnh trong từng tình huống cụ thể. Tuy nhiên mức sâu nhất mà bạn có thể nhìn vào hệ thống là biết thuật toán nào đã được sử dụng cho câu lệnh, do Microsoft che dấu toàn bộ các chi tiết bên dưới. Việc hiểu biết cơ chế hoạt động của các thuật toán giúp bạn có thêm một công cụ để tối ưu hóa câu lệnh. Ví dụ, với câu truy vấn ở phần Hash Join, khi quan sát kế hoạch thực thi và thấy Hash Join được sử dụng bạn hiểu rằng đây có thể là chỉ dấu câu lệnh chưa được thực hiện tối ưu. Bạn cố gắng tạo thay đổi để hệ thống chuyển sang chọn Merge Join (vì số bản ghi trả về lớn nên Nested Loop Join chắc chắn không thích hợp). Để d ùng Merge Join thì đầu vào phải được sắp xếp. Vì thế bạn có thể sửa lại index trên trường ProductID để nó cover cả trường OrderQty. Và giờ câu lệnh đã được thực hiện bằng Merge Join và hiệu năng đã được cải thiện đáng kể: Code: --Tạo một bảng copy của Sales.SalesOrderDetail SELECT * INTO Sales.SalesOrderDetail_2 FROM Sales.SalesOrderDetail GO -- tạo các index trên bảng copy CREATE CLUSTERED INDEX IX_SalesOrderDetail_SalesOrderID_SalesOrderDetailID_2 ON Sales.SalesOrderDetail_2 ( SalesOrderID, SalesOrderDetailID) GO CREATE NONCLUSTERED INDEX IX_SalesOrderDetail_ProductID_2 ON Sales.SalesOrderDetail_2(ProductID) INCLUDE(OrderQty) -- so sánh hai câu lệnh: -- Query 1: câu lệnh trên bảng cũ SELECT a.SalesOrderDetailID, a.OrderQty, b.Name FROM Sales.SalesOrderDetail a JOIN Production.Product b ON a.ProductID = b.ProductID -- Query 2: câu lệnh trên bảng copy SELECT a.SalesOrderDetailID, a.OrderQty, b.Name FROM Sales.SalesOrderDetail_2 a JOIN Production.Product b
- ON a.ProductID = b.ProductID
CÓ THỂ BẠN MUỐN DOWNLOAD
-
Tài liệu CCNA
216 p | 288 | 140
-
Thao tác căn bản trên Word 2007 – Thực hiện thao tác nhập văn bản
4 p | 218 | 103
-
Visual Foxpro - Bài 7
11 p | 251 | 96
-
Tính khả tuần tự của lịch thao tác trong cơ chế Lock
12 p | 633 | 33
-
Giáo trình giới thiệu cơ bản về bộ định tuyến router và phương pháp cấu hình cổng ethernet trên router p1
6 p | 126 | 19
-
Chapter 6 – Kiến trúc bộ lệnh
34 p | 163 | 19
-
Hướng dẫn thực hành Hệ điều hành " BIÊN DỊCH VÀ CÀI ĐẶT NACHOS"
5 p | 444 | 17
-
Duyệt thanh Ribbon bằng Access Key trong Ofice 2007
4 p | 156 | 14
-
Tìm hiểu giao thức định tuyến vector - phần 9
6 p | 104 | 13
-
Hướng dẫn cấu hình giao thức định tuyến RIPng cho IPv6
4 p | 169 | 12
-
Bài giảng môn Kiến trúc máy tính và hệ điều hành: Chương 2 - ThS. Nguyễn Thị Ngọc Vinh
49 p | 115 | 11
-
Bài giảng Kiến trúc máy tính: Tuần 10 - ĐH Công nghệ thông tin
53 p | 49 | 9
-
Giáo trình phân tích quy trình vận hành ứng dụng các chế độ cấu hình toàn cục cho modem p1
6 p | 65 | 5
-
Duyệt web từ Linux Terminal với W3M
7 p | 75 | 4
-
Giáo trình hướng dẫn phân tích các chế độ cấu hình toàn cục cho router với host p3
6 p | 79 | 4
-
Giáo trình hướng dẫn phân tích các chế độ cấu hình toàn cục cho router với host p2
6 p | 51 | 4
-
Giáo trình phân tích quy trình vận hành ứng dụng các chế độ cấu hình toàn cục cho modem p7
6 p | 67 | 2
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn