2009-05-13 49 views
26

Tôi đã tự hỏi về các bảng tạm thời trong sp và cách tất cả có thể có hiệu lực đồng thời. SP được tạo trên máy chủ MSSQL 08.Các bảng tạm thời trong các thủ tục lưu sẵn

Nếu tôi có một SP mà tôi tạo ra một bảng temp và thả nó lại như thế này:

BEGIN 

CREATE TABLE #MyTempTable 
(
    someField int, 
    someFieldMore nvarchar(50) 
) 

... Use of temp table here 
... And then.. 

DROP TABLE #MyTempTable 

END 

SP này sẽ được gọi là rất rất thường xuyên, vì vậy câu hỏi của tôi là có thể có bao giờ xảy ra vấn đề đồng thời ở đây?

Trả lời

28

Không. Các phiên bản tạm thời của bảng tạm thời sẽ được tạo cho mỗi kết nối.

+0

Được rồi đó cũng là những gì tôi nghĩ .. Tôi đã lo lắng vì tôi đã sử dụng phân tích truy vấn và xây dựng một bảng tạm thời và đã có thể gọi nó là một lần nữa sau khi tôi không bỏ nó. Nhưng trong bài đăng của bạn, tôi đã thử mở một truy vấn mới và thử gọi nó từ đó mà không thành công và bây giờ tôi lại bình tĩnh :) –

+0

Nhưng hiệu suất khôn ngoan có vấn đề đồng thời lớn. – tpower

+1

@tpower: Sự hiểu biết của tôi về OP chủ yếu là về việc sửa đổi các vấn đề chia sẻ trạng thái và luồng. Rõ ràng là hiệu suất sẽ bị ảnh hưởng. –

17

Có thể.

Bảng tạm thời được bắt đầu bằng một # (#example) được lưu trên cơ sở mỗi phiên. Vì vậy, nếu mã của bạn gọi thủ tục được lưu trữ một lần nữa trong khi một cuộc gọi khác đang chạy (ví dụ như các chủ đề nền) thì cuộc gọi tạo sẽ thất bại vì nó đã có.

Nếu bạn đang thực sự lo lắng sử dụng một biến bảng thay vì

DECLARE @MyTempTable TABLE 
(
    someField int, 
    someFieldMore nvarchar(50) 
) 

này sẽ được cụ thể cho các "dụ" đó gọi thủ tục lưu trữ.

+2

Bạn không thể sử dụng lại phiên SQL, bất kể khách hàng cố gắng làm gì. – gbn

+0

"(#example) được lưu trên cơ sở mỗi phiên" Và phiên được dựa trên kết nối? –

+0

Được rồi, cảm ơn vì việc giải phóng gbn –

7

Không thực sự và tôi đang nói về SQL Server. Bảng tạm thời (với duy nhất #) tồn tại và có thể nhìn thấy trong phạm vi nó được tạo ra (phạm vi giới hạn). Mỗi lần bạn gọi thủ tục lưu sẵn của bạn, nó tạo ra một phạm vi mới và do đó bảng tạm thời chỉ tồn tại trong phạm vi đó. Tôi tin rằng các bảng tạm thời cũng hiển thị với các thủ tục được lưu trữ và các udfs được gọi trong phạm vi đó. Tuy nhiên, nếu bạn sử dụng double pound (##) thì chúng sẽ trở thành toàn cục trong phiên của bạn và do đó có thể nhìn thấy các quá trình thực thi khác như một phần của phiên làm việc bảng tạm thời được tạo ra và bạn sẽ phải suy nghĩ xem khả năng truy cập bảng tạm thời hay không đồng thời là mong muốn hay không.

-1

Cơ sở dữ liệu sử dụng cùng một khóa cho tất cả các bảng #temp vì vậy nếu bạn đang sử dụng nhiều, bạn sẽ gặp phải các sự cố bế tắc. Tốt hơn là sử dụng các biến @ table cho concurrency.

+1

-1 Điều khóa không đúng kể từ SQL Server 6.5 –

-1

Sử dụng bảng @temp bất cứ khi nào có thể - nghĩa là, bạn chỉ cần một khóa chính và bạn không cần phải truy cập dữ liệu từ một proc được lưu trữ cấp dưới.

Sử dụng bảng #temp nếu bạn cần truy cập dữ liệu từ một proc được lưu trữ cấp dưới (nó là biến toàn cục ác đối với chuỗi cuộc gọi proc được lưu trữ) và bạn không có cách nào khác để chuyển dữ liệu giữa procs được lưu trữ. Cũng sử dụng nó nếu bạn cần một chỉ số thứ cấp (mặc dù, thực sự tự hỏi mình nếu nó là một bảng #temp nếu bạn cần nhiều hơn một index)

Nếu bạn làm điều này, luôn tuyên bố bảng #temp của bạn ở phía trên của hàm. SQL sẽ buộc một biên dịch lại của proc được lưu trữ của bạn khi nó thấy bảng tạo bảng .... vì vậy nếu bạn có khai báo bảng #temp ở giữa proc được lưu trữ, bạn đã lưu trữ proc phải ngừng xử lý và biên dịch lại.

+1

-1 Không, các đối tượng tạm thời (bảng và biến) thường được lưu trong bộ nhớ cache trong SQL Server 2005 và sau đó, do đó việc biên dịch lại tránh được. Xem http://sqlblog.com/blogs/paul_white/archive/2012/08/17/temporary-object-caching-explained.aspx và http://technet.microsoft.Ví dụ: com/en-us/library/cc966545.aspx –

0

Theo sách SQL Server 2008 Bạn có thể tạo bảng tạm thời cục bộ và toàn cục. Bảng tạm thời cục bộ chỉ hiển thị trong phiên hiện tại và bảng tạm thời toàn cục hiển thị cho tất cả các phiên.

'#table_temporal

' ## table_global

Nếu một bảng tạm thời địa phương được tạo ra trong một thủ tục lưu trữ hoặc ứng dụng có thể được thực hiện đồng thời bởi nhiều người dùng, Engine Cơ sở dữ liệu phải có khả năng để phân biệt các bảng được tạo bởi những người dùng khác nhau. Cơ sở dữ liệu thực hiện điều này bằng cách gắn thêm một hậu tố dạng số vào mỗi tên bảng tạm thời cục bộ.

Sau đó, không xảy ra sự cố.

2

Đối với tất cả những người đề xuất sử dụng các biến bảng, hãy thận trọng khi làm như vậy. Biến bảng không thể được lập chỉ mục trong khi bảng tạm thời có thể được lập chỉ mục. Biến bảng là tốt nhất khi làm việc với một lượng nhỏ dữ liệu nhưng nếu bạn đang làm việc trên các tập dữ liệu lớn hơn (ví dụ: 50 nghìn bản ghi), bảng tạm thời sẽ nhanh hơn nhiều so với biến bảng.

Cũng xin lưu ý rằng bạn không thể dựa vào thử/nắm bắt để buộc dọn dẹp trong quy trình được lưu trữ. một số loại lỗi nhất định không thể bị bắt trong một thử/bắt (ví dụ: biên dịch thất bại do độ phân giải tên trì hoãn) nếu bạn muốn chắc chắn bạn có thể cần tạo một thủ tục được lưu trữ bao bọc có thể thực hiện thử/nắm bắt thủ tục lưu sẵn của nhân viên và dọn dẹp ở đó.

ví dụ: tạo công nhân proc AS BEGIN - làm cái gì ở đây END

create proc wrapper AS 
BEGIN 
    Create table #... 
    BEGIN TRY 
     exec worker 
     exec worker2 -- using same temp table 
     -- etc 
    END TRY 
    END CATCH 
     -- handle transaction cleanup here 
     drop table #... 
    END CATCH 
END 
Các vấn đề liên quan