Người thuê trước:Điều này là rất nhiều không chọn lọc ở tất cả. Có thể có rất ít biến thể trên 1 triệu hàng nếu bạn chỉ có 100 TenantID. Nhưng số liệu thống kê cho các truy vấn này chính xác hơn vì SQL Server sẽ biết rằng một truy vấn cho Người thuê A sẽ lấy lại 500.000 hàng nhưng cùng một truy vấn cho Người thuê B chỉ có 50 hàng. Đây là nơi đau chính. Phương pháp này làm tăng đáng kể khả năng gặp phải các vấn đề đánh hơi tham số trong đó lần chạy đầu tiên của Quy trình được lưu trữ dành cho Người thuê A và hành động phù hợp dựa trên Trình tối ưu hóa truy vấn xem các thống kê đó và biết rằng nó cần có hiệu quả khi nhận được 500 nghìn hàng. Nhưng khi Tenant B, chỉ với 50 hàng, chạy, kế hoạch thực hiện đó không còn phù hợp, và trên thực tế, là không phù hợp. VÀ, vì dữ liệu không được chèn theo thứ tự của trường hàng đầu,
Tuy nhiên, để TenantID đầu tiên chạy Quy trình được lưu trữ, hiệu suất phải tốt hơn so với cách tiếp cận khác vì dữ liệu (ít nhất là sau khi thực hiện bảo trì chỉ mục) sẽ được tổ chức về mặt vật lý và logic để có ít trang dữ liệu hơn để đáp ứng truy vấn. Điều này có nghĩa là I / O vật lý ít hơn, đọc ít logic hơn, ít tranh chấp hơn giữa Người thuê cho cùng một trang dữ liệu, ít lãng phí không gian hơn trong Vùng đệm (do đó Tuổi thọ Trang được cải thiện), v.v.
Có hai chi phí chính để có được hiệu suất được cải thiện này. Đầu tiên không quá khó: bạn phải bảo trì chỉ mục thường xuyên để chống lại sự phân mảnh tăng lên. Thứ hai là một chút ít vui vẻ.
Để chống lại các vấn đề đánh hơi tham số gia tăng, bạn cần tách các kế hoạch thực hiện giữa các đối tượng thuê. Cách tiếp cận đơn giản là sử dụng WITH RECOMPILE
trên procs hoặc OPTION (RECOMPILE)
gợi ý truy vấn, nhưng đó là một điểm nhấn về hiệu suất có thể xóa sạch tất cả lợi nhuận đạt được bằng cách đặt lên hàng TenantID
đầu. Phương pháp mà tôi thấy hiệu quả nhất là sử dụng SQL động được tham số hóa thông qua sp_executesql
. Lý do cần SQL động là để cho phép ghép TenantID vào văn bản của truy vấn, trong khi tất cả các vị từ khác thường là tham số vẫn là tham số. Ví dụ: nếu bạn đang tìm kiếm một Đơn hàng cụ thể, bạn sẽ làm một cái gì đó như:
DECLARE @GetOrderSQL NVARCHAR(MAX);
SET @GetOrderSQL = N'
SELECT ord.field1, ord.field2, etc.
FROM dbo.Orders ord
WHERE ord.TenantID = ' + CONVERT(NVARCHAR(10), @TenantID) + N'
AND ord.OrderID = @OrderID_dyn;
';
EXEC sp_executesql
@GetOrderSQL,
N'@OrderID_dyn INT',
@OrderID_dyn = @OrderID;
Hiệu quả của việc này là tạo ra một kế hoạch truy vấn có thể sử dụng lại cho TenantID đó sẽ khớp với khối lượng dữ liệu của Đối tượng thuê cụ thể đó. Nếu cùng một đối tượng thuê A thực hiện lại thủ tục được lưu trữ cho người khác @OrderID
thì nó sẽ sử dụng lại kế hoạch truy vấn được lưu trong bộ nhớ cache đó. Một đối tượng thuê khác đang chạy cùng một Quy trình được lưu trữ sẽ tạo ra một văn bản truy vấn chỉ khác nhau về giá trị của TenantID, nhưng bất kỳ sự khác biệt nào trong văn bản truy vấn là đủ để tạo ra một kế hoạch khác. Và gói được tạo cho Người thuê B sẽ không chỉ khớp với khối lượng dữ liệu cho Người thuê B mà còn có thể được sử dụng lại cho Người thuê B cho các giá trị khác nhau @OrderID
(vì vị từ đó vẫn được tham số hóa).
Nhược điểm của phương pháp này là:
- Đó là một công việc nhiều hơn một chút so với việc chỉ nhập một truy vấn đơn giản (nhưng không phải tất cả các truy vấn cần phải là SQL động, chỉ là những truy vấn cuối cùng có vấn đề đánh hơi tham số).
- Tùy thuộc vào số lượng Người thuê trên một hệ thống, nó sẽ tăng kích thước bộ đệm của gói vì mỗi truy vấn hiện yêu cầu 1 gói cho mỗi TenantID đang gọi nó. Điều này có thể không phải là một vấn đề, nhưng ít nhất là một cái gì đó cần phải nhận thức.
SQL động phá vỡ chuỗi sở hữu, có nghĩa là quyền truy cập đọc / ghi vào các bảng có thể được thừa nhận bằng cách có EXECUTE
quyền đối với Quy trình được lưu trữ. Cách khắc phục dễ dàng nhưng kém an toàn chỉ là cung cấp cho Người dùng quyền truy cập trực tiếp vào các bảng. Điều này chắc chắn không lý tưởng, nhưng đó thường là sự đánh đổi cho nhanh chóng và dễ dàng. Cách tiếp cận an toàn hơn là sử dụng bảo mật dựa trên Chứng chỉ. Ý nghĩa, tạo Chứng chỉ, sau đó tạo Người dùng từ Chứng chỉ đó, cấp cho Người dùng đó các quyền mong muốn (Người dùng hoặc Đăng nhập dựa trên Chứng chỉ không thể tự kết nối với Máy chủ SQL), sau đó ký vào Quy trình được lưu trữ sử dụng SQL động với điều đó cùng chứng chỉ qua THÊM ĐĂNG KÝ .
Để biết thêm thông tin về ký mô-đun và Chứng chỉ, vui lòng xem: ModuleSigning.Info