Khi nào tôi nên sử dụng biến bảng so với bảng tạm thời trong máy chủ sql?


298

Tôi đang tìm hiểu thêm chi tiết trong biến bảng. Nó nói rằng các bảng tạm thời luôn ở trên đĩa và các biến của bảng nằm trong bộ nhớ, nghĩa là hiệu suất của biến bảng tốt hơn bảng tạm thời vì biến bảng sử dụng ít thao tác IO hơn bảng tạm thời.

Nhưng đôi khi, nếu có quá nhiều bản ghi trong một biến bảng không thể chứa trong bộ nhớ, biến bảng sẽ được đưa vào đĩa như bảng tạm thời.

Nhưng tôi không biết "quá nhiều hồ sơ" là gì. 100.000 hồ sơ? hay 1000.000 hồ sơ? Làm thế nào tôi có thể biết nếu một biến bảng tôi đang sử dụng nằm trong bộ nhớ hoặc trên đĩa? Có bất kỳ chức năng hoặc công cụ nào trong SQL Server 2005 để đo tỷ lệ của biến bảng hoặc cho tôi biết khi nào biến bảng được đưa vào đĩa từ bộ nhớ không?


5
Một biến bảng gần như luôn luôn nằm trong tempDB- rằng "trong bộ nhớ" là một huyền thoại. Ngoài ra: các biến của bảng sẽ luôn được trình tối ưu hóa truy vấn xem xét để giữ chính xác một hàng - nếu bạn có nhiều hơn, điều này có thể dẫn đến các kế hoạch thực hiện tồi tệ.
marc_s

Bạn có thể tìm thấy stackoverflow
này.com/questions/27894/ Kẻ

2
@marc_s - Bạn có thể bỏ "gần như" trong tuyên bố đó. Nó luôn ở trong tempdb(nhưng cũng có thể hoàn toàn nằm trong bộ nhớ)
Martin Smith

2
Với SQL 2014, giờ đây bạn có thể tạo một biến bảng trong bộ nhớ
paparazzo

Câu trả lời:


362

Câu hỏi của bạn cho thấy bạn đã chịu thua một số quan niệm sai lầm phổ biến xung quanh các biến bảng và bảng tạm thời.

Tôi đã viết một câu trả lời khá rộng rãi trên trang DBA xem xét sự khác biệt giữa hai loại đối tượng. Điều này cũng giải quyết câu hỏi của bạn về đĩa so với bộ nhớ (Tôi không thấy bất kỳ sự khác biệt đáng kể nào trong hành vi giữa hai người).

Về câu hỏi trong tiêu đề mặc dù khi nào nên sử dụng biến bảng so với bảng tạm thời cục bộ, bạn không phải luôn có lựa chọn. Ví dụ, trong các hàm, chỉ có thể sử dụng biến bảng và nếu bạn cần ghi vào bảng trong phạm vi con thì chỉ có một #tempbảng sẽ làm (các tham số có giá trị bảng cho phép truy cập chỉ đọc ).

Trường hợp bạn có một sự lựa chọn, một số gợi ý dưới đây (mặc dù phương pháp đáng tin cậy nhất là chỉ cần kiểm tra cả hai với khối lượng công việc cụ thể của bạn).

  1. Nếu bạn cần một chỉ mục không thể được tạo trên một biến bảng thì tất nhiên bạn sẽ cần một #temporarybảng. Các chi tiết của điều này là phụ thuộc phiên bản tuy nhiên. Đối với SQL Server 2012 và thấp hơn các chỉ mục duy nhất có thể được tạo trên các biến của bảng là những chỉ mục được tạo ngầm thông qua một UNIQUEhoặc PRIMARY KEYràng buộc. SQL Server 2014 đã giới thiệu cú pháp chỉ mục nội tuyến cho một tập hợp con các tùy chọn có sẵn trong CREATE INDEX. Điều này đã được mở rộng kể từ khi cho phép các điều kiện chỉ mục được lọc. Tuy nhiên, các chỉ mục có INCLUDEcột -d hoặc chỉ mục của cột vẫn không thể tạo trên các biến của bảng.

  2. Nếu bạn sẽ liên tục thêm và xóa số lượng lớn các hàng khỏi bảng thì hãy sử dụng #temporarybảng. Điều đó hỗ trợ TRUNCATE(hiệu quả hơn so DELETEvới các bảng lớn) và các lần chèn tiếp theo sau TRUNCATEcó thể có hiệu suất tốt hơn so với các bảng theo sau DELETE như được minh họa ở đây .

  3. Nếu bạn sẽ xóa hoặc cập nhật một số lượng lớn các hàng thì bảng tạm thời có thể hoạt động tốt hơn nhiều so với biến bảng - nếu nó có thể sử dụng chia sẻ hàng (ví dụ: "Hiệu ứng chia sẻ hàng" bên dưới).
  4. Nếu kế hoạch tối ưu sử dụng bảng sẽ thay đổi tùy thuộc vào dữ liệu thì hãy sử dụng #temporarybảng. Điều đó hỗ trợ tạo số liệu thống kê cho phép kế hoạch được biên dịch lại theo dữ liệu (mặc dù đối với các bảng tạm thời được lưu trong bộ nhớ cache trong quy trình lưu trữ , hành vi biên dịch lại cần được hiểu riêng).
  5. Nếu kế hoạch tối ưu cho truy vấn sử dụng bảng không có khả năng thay đổi thì bạn có thể xem xét một biến bảng để bỏ qua chi phí tạo và biên dịch lại thống kê (có thể yêu cầu gợi ý để sửa gói bạn muốn).
  6. Nếu nguồn cho dữ liệu được chèn vào bảng là từ một SELECTcâu lệnh có khả năng đắt tiền thì hãy xem xét rằng việc sử dụng biến bảng sẽ chặn khả năng này bằng cách sử dụng một kế hoạch song song.
  7. Nếu bạn cần dữ liệu trong bảng để tồn tại trong quá trình quay lại giao dịch người dùng bên ngoài thì hãy sử dụng biến bảng. Một trường hợp sử dụng có thể cho việc này có thể là ghi nhật ký tiến trình của các bước khác nhau trong một lô SQL dài.
  8. Khi sử dụng #tempbảng trong khóa giao dịch người dùng có thể được giữ lâu hơn so với biến bảng (có thể cho đến khi kết thúc giao dịch so với kết thúc câu lệnh phụ thuộc vào loại khóa và mức cô lập) và cũng có thể ngăn chặn việc cắt giảm tempdbnhật ký giao dịch cho đến khi giao dịch người dùng kết thúc. Vì vậy, điều này có thể ủng hộ việc sử dụng các biến bảng.
  9. Trong các thói quen được lưu trữ, cả hai biến bảng và bảng tạm thời có thể được lưu trữ. Việc bảo trì siêu dữ liệu cho các biến của bảng được lưu trong bộ nhớ cache ít hơn so với #temporarycác bảng. Bob Ward chỉ ra trong tempdbbài trình bày của mình rằng điều này có thể gây ra sự tranh chấp bổ sung trên các bảng hệ thống trong điều kiện đồng thời cao. Ngoài ra, khi xử lý một lượng nhỏ dữ liệu, điều này có thể tạo ra sự khác biệt có thể đo lường được đối với hiệu suất .

Tác dụng của việc chia sẻ hàng

DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);

CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);

INSERT INTO @T 
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2

SET STATISTICS TIME ON

/*CPU time = 7016 ms,  elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;

/*CPU time = 6234 ms,  elapsed time = 7236 ms.*/
DELETE FROM @T

/* CPU time = 828 ms,  elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;

/*CPU time = 672 ms,  elapsed time = 980 ms.*/
DELETE FROM #T

DROP TABLE #T

2
Xin chào, ngài Martin Smith. Trong trường hợp mi tôi chỉ muốn lưu trữ một tập hợp các giá trị Id để sử dụng chúng trong truy vấn khác trong thủ tục Store. Vì vậy, những gì bạn đề nghị tôi?
Jeancarlo Fontalvo

@JeancarloFontalvo - một biến bảng có khóa chính idvà sử dụng OPTION (RECOMPILE)có lẽ sẽ ổn cho điều đó - nhưng hãy kiểm tra cả hai.
Martin Smith

sự tranh chấp siêu dữ liệu giống nhau cho cả bảng tạm thời và biến bảng?
Syed Aqeel Ashiq

@Syed. Nói chung là ít hơn cho TV. Khóa có thể được phát hành sớm hơn nếu bên trong một giao dịch người dùng. Cũng xem liên kết Bob Ward.
Martin Smith

73

Sử dụng biến bảng nếu cho một lượng dữ liệu rất nhỏ (hàng nghìn byte)

Sử dụng bảng tạm thời cho nhiều dữ liệu

Một cách khác để suy nghĩ về nó: nếu bạn nghĩ rằng bạn có thể hưởng lợi từ một chỉ mục, số liệu thống kê tự động hoặc bất kỳ mức độ tối ưu hóa SQL nào, thì tập dữ liệu của bạn có thể quá lớn cho một biến bảng.

Trong ví dụ của tôi, tôi chỉ muốn đặt khoảng 20 hàng thành một định dạng và sửa đổi chúng thành một nhóm, trước khi sử dụng chúng để CẬP NHẬT / XÁC NHẬN một bảng cố định. Vì vậy, một biến bảng là hoàn hảo.

Nhưng tôi cũng đang chạy SQL đến hàng ngàn back-fill hàng tại một thời điểm, và tôi chắc chắn có thể nói rằng các bảng tạm thời thực hiện nhiều hơn các biến bảng.

Điều này không giống với cách mà CTE quan tâm vì một lý do kích thước tương tự - nếu dữ liệu trong CTE rất nhỏ, tôi thấy CTE hoạt động tốt hoặc tốt hơn so với những gì trình tối ưu hóa đưa ra, nhưng nếu nó khá lớn thì nó làm bạn đau

Sự hiểu biết của tôi chủ yếu dựa trên http://www.developerfusion.com/article/84397/table-variabled-v-t tạm-tables-in-sql-server / , có nhiều chi tiết hơn.


Biến takeaway là biến bảng là tốt cho tập dữ liệu nhỏ, nhưng sử dụng bảng tạm thời cho tập dữ liệu lớn hơn. Tôi có một truy vấn với hàng ngàn hàng. Bằng cách chuyển từ biến bảng sang bảng tạm thời, thời gian truy vấn giảm từ 40 giây xuống chỉ còn 5 giây với mọi thứ khác bằng nhau.
liang

42

Microsoft nói ở đây

Các biến bảng không có số liệu thống kê phân phối, chúng sẽ không kích hoạt biên dịch lại. Do đó, trong nhiều trường hợp, trình tối ưu hóa sẽ xây dựng một kế hoạch truy vấn dựa trên giả định rằng biến bảng không có hàng. Vì lý do này, bạn nên thận trọng khi sử dụng biến bảng nếu bạn mong đợi số lượng hàng lớn hơn (lớn hơn 100). Bảng Temp có thể là một giải pháp tốt hơn trong trường hợp này.


14

Tôi hoàn toàn đồng ý với Bàn tính (xin lỗi - không có đủ điểm để nhận xét).

Ngoài ra, hãy nhớ rằng nó không nhất thiết phải có bao nhiêu hồ sơ bạn có, nhưng kích thước của hồ sơ của bạn.

Chẳng hạn, bạn đã xem xét sự khác biệt về hiệu suất giữa 1.000 bản ghi với 50 cột mỗi cột so với 100.000 bản ghi chỉ có 5 cột chưa?

Cuối cùng, có thể bạn đang truy vấn / lưu trữ nhiều dữ liệu hơn mức bạn cần? Đây là một bài đọc tốt về các chiến lược tối ưu hóa SQL . Giới hạn số lượng dữ liệu bạn đang kéo, đặc biệt là nếu bạn không sử dụng tất cả (một số lập trình viên SQL trở nên lười biếng và chỉ chọn mọi thứ mặc dù họ chỉ sử dụng một tập hợp con nhỏ). Đừng quên trình phân tích truy vấn SQL cũng có thể trở thành người bạn tốt nhất của bạn.


4

Bảng biến chỉ có sẵn cho phiên hiện tại, ví dụ: nếu bạn cần EXECmột quy trình được lưu trữ khác trong quy trình hiện tại, bạn sẽ phải vượt qua bảng vì Table Valued Parametertất nhiên điều này sẽ ảnh hưởng đến hiệu suất, với các bảng tạm thời bạn chỉ có thể làm điều này với vượt qua tên bảng tạm thời

Để kiểm tra bảng tạm thời:

  • Quản lý truy vấn mở phòng thu
  • Tạo một bảng tạm thời
  • Mở một cửa sổ soạn thảo truy vấn khác
  • Chọn từ bảng này "Có sẵn"

Để kiểm tra bảng Biến:

  • Quản lý truy vấn mở phòng thu
  • Tạo một bảng biến
  • Mở một cửa sổ soạn thảo truy vấn khác
  • Chọn từ bảng này "Không có sẵn"

một thứ khác tôi đã trải nghiệm là: Nếu lược đồ của bạn không có GRANTđặc quyền để tạo các bảng thì hãy sử dụng các bảng biến.


3

ghi dữ liệu vào các bảng được khai báo declare @tbvà sau khi nối với các bảng khác, tôi nhận ra rằng thời gian phản hồi so với các bảng tạm thời tempdb .. # tbcao hơn nhiều.

Khi tôi tham gia cùng họ với @tb , thời gian trả về kết quả lâu hơn nhiều, không giống như #tm , việc trả lại gần như tức thời.

Tôi đã thực hiện các thử nghiệm với 10.000 hàng tham gia và tham gia với 5 bảng khác


Bạn có thể đăng bài kiểm tra bạn đã chạy để có được những số liệu này?
Dan Def
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.