Tạo một bảng là một hoạt động tương đối tốn nhiều tài nguyên và thời gian. Máy chủ phải định vị và phân bổ không gian lưu trữ cho cấu trúc chỉ mục và dữ liệu mới, đồng thời tạo các mục nhập tương ứng trong nhiều bảng siêu dữ liệu hệ thống. Tất cả công việc này phải được thực hiện theo những cách sẽ luôn hoạt động chính xác trong điều kiện đồng thời cao và đáp ứng tất cả các đảm bảo ACID được mong đợi của một cơ sở dữ liệu quan hệ.
Trong SQL Server, điều này có nghĩa là sử dụng đúng loại khóa và chốt theo trình tự chính xác, đồng thời đảm bảo rằng các mục nhập nhật ký giao dịch chi tiết được cam kết lưu trữ liên tục một cách an toàn trước bất kỳ thay đổi vật lý nào đối với cơ sở dữ liệu. Các mục nhật ký này đảm bảo hệ thống có thể đưa cơ sở dữ liệu trở lại trạng thái nhất quán trong trường hợp khôi phục giao dịch hoặc sự cố hệ thống.
Làm rơi bàn là một hoạt động tương tự tốn kém. May mắn thay, hầu hết các cơ sở dữ liệu không tạo hoặc giảm bảng với bất kỳ tần suất lớn nào. Ngoại lệ rõ ràng cho điều này là cơ sở dữ liệu hệ thống tempdb . Cơ sở dữ liệu duy nhất này chứa lưu trữ vật lý, cấu trúc phân bổ, siêu dữ liệu hệ thống và các mục nhập nhật ký giao dịch cho tất cả các bảng tạm thời và các biến bảng trên toàn bộ phiên bản SQL Server.
Bản chất của bảng tạm thời và các biến bảng sẽ được tạo và loại bỏ thường xuyên hơn nhiều so với các kiểu đối tượng cơ sở dữ liệu khác. Khi tần suất tạo và phá hủy tự nhiên cao này được kết hợp với hiệu ứng tập trung của tất cả các bảng tạm thời và các biến bảng được liên kết với một cơ sở dữ liệu duy nhất, thì hầu như không có gì đáng ngạc nhiên khi có thể nảy sinh tranh chấp trong cấu trúc phân bổ và siêu dữ liệu của tempdb cơ sở dữ liệu.
Bộ nhớ đệm đối tượng tạm thời
Để giảm tác động đến tempdb cấu trúc, SQL Server có thể lưu vào bộ đệm các đối tượng tạm thời để sử dụng lại. Thay vì bỏ một đối tượng tạm thời, SQL Server giữ lại siêu dữ liệu hệ thống và cắt bớt dữ liệu bảng. Nếu bảng có dung lượng 8MB hoặc nhỏ hơn, việc cắt bớt được thực hiện đồng bộ; nếu không thì thả chậm được sử dụng. Trong cả hai trường hợp, việc cắt bớt làm giảm yêu cầu lưu trữ xuống một trang dữ liệu (trống) và thông tin phân bổ cho một trang IAM duy nhất.
Bộ nhớ đệm tránh được hầu như tất cả chi phí phân bổ và siêu dữ liệu khi tạo đối tượng tạm thời vào lần sau. Do tác dụng phụ của việc thực hiện ít thay đổi hơn đối với tempdb cơ sở dữ liệu hơn là một chu kỳ tái tạo và thả đầy đủ, bộ nhớ đệm đối tượng tạm thời cũng làm giảm số lượng ghi nhật ký giao dịch cần thiết.
Đạt được bộ nhớ đệm
Các biến bảng và bảng tạm thời cục bộ đều có khả năng được lưu vào bộ nhớ đệm. Để đủ điều kiện cho bộ nhớ đệm, bảng tạm thời cục bộ hoặc biến bảng phải được tạo trong một mô-đun:
- Thủ tục được lưu trữ (bao gồm cả thủ tục được lưu trữ tạm thời)
- Trình kích hoạt
- Hàm có giá trị trong bảng nhiều câu lệnh
- Hàm vô hướng do người dùng xác định
Giá trị trả về của một hàm có giá trị trong bảng nhiều câu lệnh là một biến bảng, bản thân nó có thể được lưu vào bộ nhớ đệm. Các tham số có giá trị bảng (cũng là các biến bảng) có thể được lưu vào bộ nhớ đệm khi tham số được gửi từ ứng dụng khách, ví dụ:trong mã .NET sử dụng SqlDbType.Structured
. Khi câu lệnh được tham số hóa, cấu trúc tham số giá trị bảng chỉ có thể được lưu vào bộ nhớ đệm trên SQL Server 2012 trở lên.
Điều sau không thể được lưu vào bộ nhớ đệm:
- Bảng tạm thời toàn cầu
- Các đối tượng được tạo bằng SQL đặc biệt
- Các đối tượng được tạo bằng SQL động (ví dụ:sử dụng
EXECUTE
hoặcsys.sp_executesql
)
Để được lưu vào bộ nhớ đệm, một đối tượng tạm thời cũng không được :
- Có các ràng buộc được đặt tên (các ràng buộc không có tên rõ ràng là hoàn toàn ổn)
- Thực hiện "DDL" sau khi tạo đối tượng
- Ở trong một mô-đun được xác định bằng
WITH RECOMPILE
lựa chọn - Được gọi bằng
WITH RECOMPILE
tùy chọn củaEXECUTE
tuyên bố
Để giải quyết một số quan niệm sai lầm phổ biến một cách rõ ràng:
-
TRUNCATE TABLE
không ngăn chặn bộ nhớ đệm -
DROP TABLE
không ngăn chặn bộ nhớ đệm -
UPDATE STATISTICS
không ngăn chặn bộ nhớ đệm - Tự động tạo thống kê không ngăn chặn bộ nhớ đệm
- Thủ công
CREATE STATISTICS
sẽ ngăn chặn bộ nhớ đệm
Tất cả các đối tượng tạm thời trong một mô-đun được đánh giá về tính phù hợp với bộ nhớ đệm một cách riêng biệt. Mô-đun có chứa một hoặc nhiều đối tượng tạm thời không thể được lưu vào bộ đệm vẫn có thể đủ điều kiện để lưu vào bộ nhớ đệm của các đối tượng tạm thời khác trong cùng một mô-đun.
Một mẫu phổ biến vô hiệu hóa bộ nhớ đệm cho các bảng tạm thời là việc tạo các chỉ mục sau câu lệnh tạo bảng ban đầu. Trong hầu hết các trường hợp, điều này có thể được giải quyết bằng cách sử dụng khóa chính và các ràng buộc duy nhất. Trong SQL Server 2014 trở lên, chúng tôi có tùy chọn thêm các chỉ mục không phân nhánh không phải duy nhất trực tiếp trong câu lệnh tạo bảng bằng cách sử dụng INDEX
mệnh đề.
Giám sát và Bảo trì
Chúng tôi có thể xem có bao nhiêu đối tượng tạm thời hiện đang được lưu trong bộ nhớ đệm bằng cách sử dụng bộ đếm bộ đệm DMV:
CHỌN DOMCC. [type], DOMCC.pages_kb, DOMCC.pages_in_use_kb, DOMCC.entries_count, DOMCC.entries_in_use_countFROM sys.dm_os_memory_cache_counters AS DOMCC WHERE DOMCC. [name] =N'Temporary Tables &Table Variables.Một kết quả ví dụ là:
Mục nhập bộ nhớ cache được coi là đang được sử dụng miễn là bất kỳ phần nào của mô-đun chứa đang thực thi. Việc thực thi đồng thời của cùng một mô-đun sẽ dẫn đến việc tạo ra nhiều đối tượng tạm thời được lưu trong bộ nhớ cache. Nhiều kế hoạch thực thi cho cùng một mô-đun (có thể do phiên khác nhau
SET
tùy chọn) cũng sẽ dẫn đến nhiều mục nhập bộ nhớ cache cho cùng một mô-đun.Các mục nhập trong bộ nhớ cache có thể bị già đi theo thời gian để đáp ứng nhu cầu cạnh tranh về bộ nhớ. Các đối tượng tạm thời được lưu trong bộ đệm cũng có thể bị xóa (không đồng bộ, bởi một luồng hệ thống nền) khi kế hoạch thực thi của mô-đun mẹ bị xóa khỏi bộ đệm kế hoạch.
Mặc dù không được hỗ trợ (hoặc theo bất kỳ cách nào được khuyến nghị) cho các hệ thống sản xuất, bộ nhớ cache của đối tượng tạm thời có thể được xóa hoàn toàn theo cách thủ công cho mục đích thử nghiệm với:
DBCC FREESYSTEMCACHE ('Bảng Tạm thời &Biến Bảng') VỚI MARK_IN_USE_FOR_REMOVAL; WAITFOR DELAY '00:00:05 ';Độ trễ năm giây cho phép thời gian chạy tác vụ dọn dẹp nền. Lưu ý rằng lệnh này thực sự nguy hiểm . Bạn chỉ nên sử dụng nó (tự chịu rủi ro) trên một phiên bản thử nghiệm mà bạn có quyền truy cập độc quyền. Khi bạn đã kiểm tra xong, hãy khởi động lại phiên bản SQL Server.
Chi tiết triển khai bộ nhớ đệm
Các biến bảng được triển khai bởi một bảng người dùng 'thực' trong tempdb cơ sở dữ liệu (mặc dù không phải là một bảng mà chúng ta có thể truy vấn trực tiếp). Tên của bảng được liên kết là "#" theo sau là biểu diễn thập lục phân tám chữ số của id đối tượng. Truy vấn sau đây cho thấy mối quan hệ:
- Một biến bảngDECLARE @Z AS table (z số nguyên NULL); - Mục nhập sys.tables tương ứngSELECT T. [name], ObjIDFromName =CONVERT (số nguyên, CONVERT (nhị phân (4), RIGHT (T. [tên], 8), 2)), T. [object_id], T. [ type_desc], T.create_date, T.modify_dateFROM tempdb.sys.tables AS T WHERE T. [name] LIKE N '# [0-9A-F] [0-9A-F] [0-9A-F] [0 -9A-F] [0-9A-F] [0-9A-F] [0-9A-F] [0-9A-F] ';Một kết quả mẫu được hiển thị bên dưới. Lưu ý cách id đối tượng được tính toán từ tên đối tượng khớp với id đối tượng thực tế:
Chạy tập lệnh đó dưới dạng SQL đặc biệt sẽ tạo ra một tempdb khác ID đối tượng (và tên đối tượng) trên mỗi lần thực thi (không có bộ nhớ đệm). Việc đặt cùng một tập lệnh bên trong một mô-đun (ví dụ:một thủ tục được lưu trữ) sẽ cho phép biến bảng được lưu vào bộ nhớ đệm (miễn là không sử dụng SQL động), do đó ID và tên đối tượng sẽ giống nhau trên mỗi lần thực thi.
Khi biến bảng không được lưu trong bộ nhớ cache, bảng bên dưới sẽ được tạo và xóa mỗi lần. Khi bộ nhớ đệm đối tượng tạm thời được bật, bảng sẽ bị cắt bớt ở cuối mô-đun thay vì bị loại bỏ. Không có không có thay đổi nào vào siêu dữ liệu hệ thống khi một biến bảng được lưu vào bộ nhớ đệm. Tác động lên cấu trúc phân bổ và ghi nhật ký giao dịch được giới hạn ở việc xóa các hàng trong bảng và xóa mọi dữ liệu thừa và các trang phân bổ khi mô-đun kết thúc.
Bảng tạm thời
Khi một bảng tạm thời được sử dụng thay vì một biến bảng, cơ chế cơ bản về cơ bản giống nhau, chỉ với một vài bước đổi tên bổ sung:Khi bảng tạm thời không được lưu trong bộ nhớ cache , nó được hiển thị trong tempdb với tên quen thuộc do người dùng cung cấp, theo sau là một loạt dấu gạch dưới và biểu diễn hệ thập lục phân của id đối tượng dưới dạng hậu tố cuối cùng. Bảng tạm thời cục bộ vẫn còn cho đến khi nó bị loại bỏ rõ ràng hoặc cho đến khi phạm vi mà nó được tạo kết thúc. Đối với SQL đặc biệt, điều này có nghĩa là khi phiên ngắt kết nối khỏi máy chủ.
Đối với bảng tạm thời được lưu trong bộ nhớ cache , lần đầu tiên mô-đun được chạy, bảng tạm thời được tạo giống như đối với trường hợp không được lưu trong bộ nhớ cache. Vào cuối mô-đun, thay vì tự động bị loại bỏ (khi phạm vi mà nó được tạo kết thúc), bảng tạm thời bị cắt bớt và sau đó được đổi tên đối với biểu diễn thập lục phân của ID đối tượng (chính xác như đã thấy đối với biến bảng). Lần tiếp theo khi mô-đun chạy, bảng đã lưu trong bộ nhớ cache được đổi tên từ định dạng thập lục phân thành tên do người dùng cung cấp (cộng với dấu gạch dưới cộng với id đối tượng hex).
Các hoạt động đổi tên bổ sung ở đầu và cuối mô-đun liên quan đến một số lượng nhỏ thay đổi siêu dữ liệu hệ thống . Do đó, các bảng tạm thời được lưu trong bộ đệm vẫn có thể gặp phải ít nhất một số tranh chấp về siêu dữ liệu với tỷ lệ sử dụng lại rất cao. Tuy nhiên, tác động siêu dữ liệu của bảng tạm thời được lưu trong bộ nhớ cache thấp hơn nhiều so với trường hợp không được lưu trong bộ nhớ cache (mỗi lần tạo và xóa bảng).
Có thể tìm thấy thêm chi tiết và ví dụ về cách hoạt động của bộ nhớ đệm đối tượng tạm thời trong bài viết trước của tôi.
Thống kê về các bảng tạm thời được lưu trong bộ nhớ cache
Như đã đề cập trước đó, thống kê có thể được tự động được tạo trên các bảng tạm thời mà không làm mất lợi thế của bộ nhớ đệm đối tượng tạm thời (xin nhắc lại, việc tạo thống kê sẽ theo cách thủ công tắt bộ nhớ đệm).
Một lưu ý quan trọng là số liệu thống kê được liên kết với bảng tạm thời được lưu trong bộ nhớ cache không được đặt lại khi đối tượng được lưu vào bộ đệm ở cuối mô-đun hoặc khi đối tượng được lưu trong bộ đệm được truy xuất từ bộ đệm ở đầu mô-đun. Do đó, số liệu thống kê trên một bảng tạm thời được lưu trong bộ nhớ cache có thể còn sót lại từ một lần thực thi trước đó không liên quan. Nói cách khác, số liệu thống kê có thể hoàn toàn không có mối liên hệ nào vào nội dung hiện tại của bảng tạm thời.
Điều này rõ ràng là không mong muốn, vì lý do chính để thích một bảng tạm thời cục bộ hơn một biến bảng là sự sẵn có của thống kê phân phối chính xác. Trong giảm thiểu, thống kê sẽ tự động được cập nhật khi (nếu) số lượng thay đổi tích lũy đối với đối tượng được lưu trong bộ nhớ cache bên dưới đạt đến Ngưỡng biên dịch nội bộ. Điều này rất khó để đánh giá trước vì các chi tiết phức tạp và hơi phản trực giác.
Cách giải quyết toàn diện nhất, trong khi vẫn giữ được các lợi ích của bộ nhớ đệm đối tượng tạm thời, là:
-
UPDATE STATISTICS
theo cách thủ công trên bảng tạm thời trong mô-đun; và - Thêm
OPTION (RECOMPILE)
gợi ý cho các câu lệnh tham chiếu đến bảng tạm thời
Đương nhiên, có một chi phí liên quan đến việc này, nhưng điều này thường được chấp nhận. Thật vậy, bằng cách chọn sử dụng một bảng tạm thời cục bộ ngay từ đầu, tác giả mô-đun đang ngầm nói rằng việc lựa chọn kế hoạch có thể nhạy cảm với nội dung của bảng tạm thời, vì vậy việc biên dịch lại có thể có ý nghĩa. Cập nhật số liệu thống kê theo cách thủ công đảm bảo rằng số liệu thống kê được sử dụng trong quá trình biên dịch lại phản ánh nội dung hiện tại của bảng (như chúng tôi chắc chắn mong đợi).
Để biết thêm chi tiết về cách hoạt động chính xác của điều này, vui lòng xem bài viết trước của tôi về chủ đề này.
Tóm tắt và Đề xuất
Bộ nhớ đệm đối tượng tạm thời trong một mô-đun có thể làm giảm đáng kể áp lực lên cấu trúc phân bổ và siêu dữ liệu được chia sẻ trong tempdb cơ sở dữ liệu. Sự giảm thiểu lớn nhất sẽ xảy ra khi sử dụng các biến bảng vì bộ nhớ đệm và sử dụng lại các đối tượng tạm thời này hoàn toàn không liên quan đến việc sửa đổi siêu dữ liệu (không có thao tác đổi tên). Vẫn có thể thấy tranh luận về cấu trúc phân bổ nếu trang dữ liệu được lưu trong bộ nhớ cache duy nhất không đủ để chứa tất cả dữ liệu của biến bảng trong thời gian chạy.
Tác động đến chất lượng kế hoạch do thiếu thông tin cơ bản cho các biến bảng có thể được giảm thiểu bằng cách sử dụng OPTION (RECOMPILE)
hoặc cờ theo dõi 2453 (khả dụng từ SQL Server 2012 trở đi). Lưu ý rằng những giảm thiểu này chỉ cung cấp cho trình tối ưu hóa thông tin về tổng số hàng trong bảng.
Để tổng quát hóa, biến bảng được sử dụng tốt nhất khi dữ liệu nhỏ (lý tưởng là phù hợp trong một trang dữ liệu duy nhất để mang lại lợi ích tranh chấp tối đa) và khi việc lựa chọn kế hoạch không phụ thuộc vào các giá trị có trong biến bảng.
Nếu thông tin về phân phối dữ liệu (mật độ và biểu đồ) rất quan trọng đối với việc lựa chọn kế hoạch, hãy sử dụng bảng tạm thời cục bộ thay thế. Đảm bảo đáp ứng các điều kiện cho bộ nhớ đệm bảng tạm thời, thường có nghĩa là không tạo chỉ mục hoặc thống kê sau câu lệnh tạo bảng ban đầu. Điều này được thực hiện thuận tiện hơn từ SQL Server 2014 trở đi do sự ra đời của INDEX
mệnh đề của CREATE TABLE
tuyên bố.
UPDATE STATISTICS
rõ ràng sau khi dữ liệu được tải vào bảng tạm thời và OPTION (RECOMPILE)
gợi ý về các câu lệnh tham chiếu bảng có thể cần thiết để tạo ra tất cả các lợi ích mong đợi của các bảng tạm thời được lưu trong bộ nhớ cache trong một mô-đun.
Điều quan trọng là chỉ sử dụng các đối tượng tạm thời khi chúng tạo ra lợi ích rõ ràng, thường là về chất lượng kế hoạch. Việc sử dụng các đối tượng tạm thời quá mức, không hiệu quả hoặc không cần thiết có thể dẫn đến tempdb tranh luận, ngay cả khi đạt được bộ nhớ đệm đối tượng tạm thời.
Bộ nhớ đệm đối tượng tạm thời tối ưu có thể không đủ để giảm tempdb đề cập đến mức có thể chấp nhận được trong mọi trường hợp, ngay cả khi các đối tượng tạm thời chỉ được sử dụng khi được chứng minh đầy đủ. Sử dụng các biến bảng trong bộ nhớ hoặc bảng trong bộ nhớ không bền có thể cung cấp các giải pháp được nhắm mục tiêu trong những trường hợp như vậy, mặc dù luôn phải đánh đổi và không có giải pháp duy nhất nào hiện đại diện cho lựa chọn tốt nhất trong mọi trường hợp.