Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Vấn đề Halloween - Phần 3

[Phần 1 | Phần 2 | Phần 3 | Phần 4]

MERGE câu lệnh (được giới thiệu trong SQL Server 2008) cho phép chúng tôi thực hiện hỗn hợp INSERT , UPDATEDELETE các hoạt động sử dụng một câu lệnh duy nhất. Các vấn đề về Bảo vệ Halloween cho MERGE chủ yếu là sự kết hợp của các yêu cầu của các hoạt động riêng lẻ, nhưng có một số khác biệt quan trọng và một số tối ưu hóa thú vị chỉ áp dụng cho MERGE .

Tránh vấn đề Halloween với MERGE

Chúng ta bắt đầu bằng cách xem lại ví dụ Demo và Staging từ phần hai:

 TẠO BẢNG dbo.Demo (SomeKey số nguyên KHÔNG NULL, CONSTRAINT PK_Demo PRIMARY KEY (SomeKey)); TẠO BẢNG dbo.Staging (số nguyên SomeKey KHÔNG NULL); CHÈN GIÁ TRỊ dbo.Staging (SomeKey) (1234), (1234); TẠO CHỈ SỐ KHÔNG ĐƯỢC ĐIỀU CHỈNH c TRÊN dbo.Staging (SomeKey); INSERT dbo.DemoSELECT s.SomeKeyFROM dbo.Staging AS sWHERE KHÔNG TỒN TẠI (CHỌN 1 TỪ dbo.Demo AS d WHERE d.SomeKey =s.SomeKey); 

Như bạn có thể nhớ lại, ví dụ này được sử dụng để chỉ ra rằng một INSERT yêu cầu Bảo vệ Halloween khi bảng mục tiêu chèn cũng được tham chiếu trong SELECT một phần của truy vấn (EXISTS trong trường hợp này). Hành vi đúng cho INSERT tuyên bố ở trên là cố gắng thêm cả hai 1234 giá trị và do đó không thành công với PRIMARY KEY sự vi phạm. Không có sự phân tách pha, INSERT sẽ thêm sai một giá trị, hoàn thành mà không có lỗi.

Kế hoạch thực thi INSERT

Đoạn mã trên có một điểm khác biệt so với đoạn mã được sử dụng trong phần hai; một chỉ mục không hợp nhất trên bảng Staging đã được thêm vào. INSERT kế hoạch thực hiện vẫn yêu cầu Bảo vệ Halloween mặc dù:

Kế hoạch thực thi MERGE

Bây giờ, hãy thử cùng một cách chèn logic được thể hiện bằng MERGE cú pháp:

 MERGE dbo.Demo AS dUSING dbo.Staging AS s ON s.SomeKey =d.SomeKeyWHEN KHÔNG ĐƯỢC PHÉP THEO MỤC TIÊU THÌ CHÈN (SomeKey) CÁC GIÁ TRỊ (s.SomeKey); 

Trong trường hợp bạn không quen với cú pháp, logic ở đó là so sánh các hàng trong bảng Staging và Demo trên giá trị SomeKey và nếu không tìm thấy hàng phù hợp nào trong bảng đích (Demo), chúng tôi sẽ chèn một hàng mới. Điều này có ngữ nghĩa chính xác giống như INSERT...WHERE NOT EXISTS mã, tất nhiên. Tuy nhiên, kế hoạch thực hiện khá khác nhau:

Lưu ý rằng kế hoạch này thiếu một Eager Table Spool. Mặc dù vậy, truy vấn vẫn tạo ra thông báo lỗi chính xác. Có vẻ như SQL Server đã tìm ra cách để thực thi MERGE lập kế hoạch lặp đi lặp lại trong khi vẫn tôn trọng sự phân chia giai đoạn hợp lý theo yêu cầu của tiêu chuẩn SQL.

Tối ưu hóa việc lấp đầy lỗ

Trong các trường hợp thích hợp, trình tối ưu hóa SQL Server có thể nhận ra rằng MERGE tuyên bố là lấp đầy lỗ , chỉ là một cách nói khác rằng câu lệnh chỉ thêm các hàng có khoảng trống hiện có trong khóa của bảng đích.

Để tối ưu hóa này được áp dụng, các giá trị được sử dụng trong WHEN NOT MATCHED BY TARGET mệnh đề phải chính xác khớp với ON một phần của USING mệnh đề. Ngoài ra, bảng đích phải có một khóa duy nhất (một yêu cầu được đáp ứng bởi PRIMARY KEY Trong trường hợp hiện tại). Khi các yêu cầu này được đáp ứng, MERGE tuyên bố không yêu cầu bảo vệ khỏi Vấn đề Halloween.

Tất nhiên, MERGE tuyên bố là về mặt logic không hơn không kém lấp đầy lỗ so với INSERT...WHERE NOT EXISTS cú pháp. Sự khác biệt là trình tối ưu hóa có toàn quyền kiểm soát việc triển khai MERGE câu lệnh, trong khi INSERT cú pháp sẽ yêu cầu nó lý luận về ngữ nghĩa rộng hơn của truy vấn. Con người có thể dễ dàng nhận thấy rằng INSERT cũng lấp đầy lỗ hổng, nhưng trình tối ưu hóa không nghĩ về mọi thứ theo cách chúng ta làm.

Để minh họa đối sánh chính xác yêu cầu mà tôi đã đề cập, hãy xem xét cú pháp truy vấn sau đây không hưởng lợi từ việc tối ưu hóa việc lấp đầy lỗ. Kết quả là Bảo vệ Halloween đầy đủ được cung cấp bởi Eager Table Spool:

 MERGE dbo.Demo AS dUSING dbo .Staging AS s ON s.SomeKey =d. 

Sự khác biệt duy nhất ở đó là phép nhân với một trong VALUES mệnh đề - điều gì đó không thay đổi logic của truy vấn, nhưng đủ để ngăn việc áp dụng tối ưu hóa lấp đầy lỗ hổng.

Lấp lỗ bằng các vòng lặp lồng nhau

Trong ví dụ trước, trình tối ưu hóa đã chọn tham gia các bảng bằng cách sử dụng phép kết hợp Hợp nhất. Tối ưu hóa lấp đầy lỗ cũng có thể được áp dụng khi bạn chọn phép nối Các vòng lặp lồng nhau, nhưng điều này yêu cầu đảm bảo tính duy nhất bổ sung trên bảng nguồn và tìm kiếm chỉ mục ở phía bên trong của phép nối. Để xem điều này trong thực tế, chúng tôi có thể xóa dữ liệu tổ chức hiện có, thêm tính duy nhất vào chỉ mục không phân biệt và thử MERGE một lần nữa:

 - Loại bỏ các hàng trùng lặp hiện cóTRUNCATE TABLE dbo.Staging; - Chuyển đổi chỉ mục thành CHỈ SỐ KHÔNG ĐƯỢC ĐIỀU CHỈNH ĐỘC ĐÁO duy nhất c TRÊN dbo.Staging (SomeKey) WITH (DROP_EXISTING =ON); - Dữ liệu mẫuINSERT dbo.Staging (SomeKey) VALUES (1234), (5678); - Hole-fill mergeMERGE dbo.Demo AS dUSING dbo.Staging AS s ON s.SomeKey =d. 

Kế hoạch thực thi kết quả một lần nữa sử dụng tối ưu hóa lấp đầy lỗ để tránh Bảo vệ Halloween, sử dụng kết hợp các vòng lặp lồng nhau và tìm kiếm bên trong vào bảng mục tiêu:

Tránh duyệt chỉ mục không cần thiết

Khi áp dụng tối ưu hóa lấp đầy lỗ, động cơ cũng có thể áp dụng một tối ưu hóa khác. Nó có thể nhớ vị trí chỉ mục hiện tại trong khi đọc bảng đích (xử lý từng hàng một, hãy nhớ) và sử dụng lại thông tin đó khi thực hiện chèn, thay vì tìm kiếm b-tree để tìm vị trí chèn. Lý do là vị trí đọc hiện tại rất có thể nằm trên cùng một trang mà hàng mới sẽ được chèn vào. Việc kiểm tra xem hàng trên thực tế có thuộc về trang này không rất nhanh, vì nó chỉ bao gồm việc kiểm tra các khóa thấp nhất và cao nhất hiện được lưu trữ ở đó.

Việc kết hợp loại bỏ Bộ đệm Bảng Eager và lưu điều hướng chỉ mục trên mỗi hàng có thể mang lại lợi ích đáng kể trong khối lượng công việc OLTP, miễn là kế hoạch thực thi được truy xuất từ ​​bộ đệm. Chi phí biên dịch cho MERGE các câu lệnh cao hơn so với INSERT , UPDATEDELETE , vì vậy kế hoạch tái sử dụng là một cân nhắc quan trọng. Nó cũng hữu ích để đảm bảo rằng các trang có đủ không gian trống để chứa các hàng mới, tránh tình trạng tách trang. Điều này thường đạt được thông qua duy trì chỉ mục bình thường và chỉ định một FILLFACTOR phù hợp .

Tôi đề cập đến khối lượng công việc OLTP, thường có một số lượng lớn các thay đổi tương đối nhỏ, bởi vì MERGE tối ưu hóa có thể không phải là một lựa chọn tốt khi một số lượng lớn các hàng được xử lý trên mỗi câu lệnh. Các tối ưu hóa khác như INSERTs được ghi nhật ký tối thiểu hiện không thể kết hợp với việc lấp lỗ. Như mọi khi, các đặc tính hiệu suất nên được đánh giá chuẩn để đảm bảo mang lại những lợi ích mong đợi.

Tối ưu hóa lấp đầy lỗ cho MERGE chèn có thể được kết hợp với cập nhật và xóa bằng cách sử dụng MERGE bổ sung điều khoản; từng thao tác thay đổi dữ liệu được đánh giá riêng cho Vấn đề Halloween.

Tránh tham gia

Tối ưu hóa cuối cùng mà chúng tôi sẽ xem xét có thể được áp dụng khi MERGE câu lệnh chứa các thao tác cập nhật và xóa cũng như chèn lấp lỗ và bảng đích có một chỉ mục được phân cụm duy nhất. Ví dụ sau đây cho thấy một MERGE phổ biến mẫu trong đó các hàng chưa khớp được chèn và các hàng phù hợp được cập nhật hoặc xóa tùy thuộc vào một điều kiện bổ sung:

 CREATE TABLE #T (col1 integer NOT NULL, col2 integer NOT NULL, CONSTRAINT PK_T PRIMARY KEY (col1)); TẠO BẢNG #S (col1 integer NOT NULL, col2 integer NOT NULL, CONSTRAINT PK_S PRIMARY KEY (col1)); CHÈN #T (col1, col2) CÁC GIÁ TRỊ (1, 50), (3, 90); CHÈN #S (col1, col2) CÁC GIÁ TRỊ (1, 40), (2, 80), (3, 90); 

MERGE tuyên bố cần thiết để thực hiện tất cả các thay đổi được yêu cầu là rất nhỏ gọn:

 MERGE #T AS tUSING #S AS s ON t.col1 =s.col1 KHÔNG ĐƯỢC PHÙ HỢP KHI CHÈN CÁC GIÁ TRỊ (s.col1, s.col2) KHI ĐÃ ĐƯỢC KẾT HỢP VÀ t.col2 - s.col2 =0 THÌ ĐÃ XÓA CẬP NHẬT CÀI ĐẶT t.col2 - =s.col2; 

Kế hoạch thực hiện khá bất ngờ:

Không có Bảo vệ Halloween, không có liên kết giữa bảng nguồn và bảng mục tiêu và bạn sẽ không thường xuyên thấy toán tử Chèn chỉ mục theo cụm được theo sau bởi phép hợp nhất chỉ mục theo cụm vào cùng một bảng. Đây là một cách tối ưu hóa khác được nhắm mục tiêu vào khối lượng công việc OLTP với khả năng tái sử dụng kế hoạch cao và lập chỉ mục phù hợp.

Ý tưởng là đọc một hàng từ bảng nguồn và ngay lập tức cố gắng chèn nó vào mục tiêu. Nếu vi phạm chính dẫn đến lỗi sẽ bị loại bỏ, toán tử Chèn sẽ xuất ra hàng xung đột mà nó tìm thấy và sau đó hàng đó được xử lý cho thao tác cập nhật hoặc xóa bằng cách sử dụng toán tử Kế hoạch hợp nhất như bình thường.

Nếu lần chèn gốc thành công (không có vi phạm khóa) thì quá trình xử lý tiếp tục với hàng tiếp theo từ nguồn (toán tử Hợp nhất chỉ xử lý cập nhật và xóa). Tối ưu hóa này chủ yếu mang lại lợi ích cho MERGE các truy vấn trong đó hầu hết các hàng nguồn dẫn đến một phần chèn. Một lần nữa, cần phải đo điểm chuẩn cẩn thận để đảm bảo hiệu suất tốt hơn so với việc sử dụng các câu lệnh riêng biệt.

Tóm tắt

MERGE tuyên bố cung cấp một số cơ hội tối ưu hóa duy nhất. Trong những trường hợp phù hợp, nó có thể tránh được sự cần thiết phải thêm Bảo vệ Halloween rõ ràng so với INSERT tương đương hoạt động, hoặc thậm chí có thể là sự kết hợp của INSERT , UPDATEDELETE các câu lệnh. MERGE bổ sung -các tối ưu hóa cụ thể có thể tránh việc duyệt qua b-cây chỉ mục thường cần thiết để xác định vị trí chèn cho một hàng mới và cũng có thể tránh hoàn toàn nhu cầu kết hợp bảng nguồn và bảng đích.

Trong phần cuối cùng của loạt bài này, chúng ta sẽ xem xét lý do của trình tối ưu hóa truy vấn về nhu cầu bảo vệ Halloween và xác định thêm một số thủ thuật mà nó có thể sử dụng để tránh phải thêm Eager Table Spools vào các kế hoạch thực thi thay đổi dữ liệu.

[Phần 1 | Phần 2 | Phần 3 | Phần 4]


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách các chỉ mục được lọc có thể trở thành một tính năng mạnh mẽ hơn

  2. Tối ưu hóa cơ sở dữ liệu:Chỉ mục

  3. Làm việc với Giao diện người dùng JavaFX và Ứng dụng JDBC

  4. Số hàng có thứ tự không xác định

  5. Triển khai một loại tùy chỉnh