2012-04-11 29 views
7

Chạy cùng Thủ tục được lưu trữ từ C# .Net application qua mạng chậm dần dần với mỗi lần thực thi tiếp theo. Dường như mất hai lần lượng thời gian như thực hiện trước đó (tối đa giá trị tối đa; đọc tiếp). Thời gian thực hiện dần dần chậm hơn cho đến khi 1 trong 2 kịch bản xảy ra, tại thời điểm đó việc thực hiện đầu tiên của SPROC là "nhanh" một lần nữa.Thời gian thực hiện chậm hơn với mỗi lần lặp lại của cùng một SPROC

  1. Nếu một SqlConnection được mở ra và vẫn mở trong tất cả các thử nghiệm, SPROC càng ngày càng chậm cho đến khi bất kỳ khác SPROC hay truy vấn được chạy.
  2. Nếu SqlConnection được mở và đóng xung quanh mỗi lần thực hiện, thì SPROC sẽ chậm dần dần cho đến khi ít nhất 8 phút đã trôi qua.

Điều này chỉ xảy ra với một vài thủ tục được lưu trữ. Một là một truy vấn đơn giản SELECT với 2 JOINs, (SPROC 1) số khác là một dòng 1600+ lớn SPROC (SPROC 2).

Thời gian thực hiện dường như không bao giờ vượt quá 60 giây chính xác cho SPROC 1 và 67 giây cho SPROC 2. SPROC 1 mất ít hơn một giây để thực hiện ban đầu và SPROC 2 mất 7 giây ban đầu.

Điều này cũng chỉ xảy ra nếu SPROC được chạy bằng cùng một số SqlConnection trong ứng dụng. Ngay khi sử dụng 2 đối tượng riêng biệt SqlConnection, chúng hoạt động giống như đã nêu ở trên, nhưng độc lập. Chạy SPROC nhiều lần trên SqlConnection1 được giảm dần dần, nhưng lần đầu tiên SPROC giống nhau chạy trên SqlConnection2, nó "nhanh". Sau đó nó sẽ bị chậm hơn khi chạy nhiều lần trên SqlConnection2.

Điều này không xảy ra nếu ứng dụng được chạy trên cùng một máy tính với SQL Server 2008 R2 được cài đặt (chạy Windows Server 2008). Thời gian thực hiện luôn nhất quán.

Chạy quy trình được lưu trữ từ bên trong Management Studio cũng không chậm hơn với mỗi lần thực thi; nó luôn luôn nhất quán.

Xóa bộ nhớ cache kế hoạch thực hiện (trong SQL Server) không ảnh hưởng đến hành vi được quan sát. Phải mất một vài ngày để thu hẹp vấn đề này ban đầu được quan sát thấy trong một ứng dụng lớn hơn nhiều, để tạo ra một ứng dụng thử nghiệm để dễ dàng kiểm tra/tái tạo nó.

Từ những gì tôi đã đọc here, có thời gian chờ từ 4 đến 8 phút (sau khi SqlConnection.Close() được gọi bằng mã) tại thời điểm đó, nó đóng kết nối cơ sở dữ liệu với nguồn dữ liệu. Điều này có vẻ phù hợp với kịch bản 2 mà tôi đã đề cập ở trên.

Điều này dẫn tôi tin rằng nó có liên quan đến SqlConnection được sử dụng (và kết nối cơ sở dữ liệu bên dưới với nguồn dữ liệu) do kết nối tổng hợp được bật trong trường hợp của tôi, nhưng tại sao tôi quan sát hành vi này và cách khắc phục nó?

Chúng tôi đang sử dụng .Net 2.0 Framework, nếu điều đó tạo ra bất kỳ sự khác biệt nào.

Có nhiều chi tiết đẹp được liệt kê ở trên, vì vậy vui lòng cho tôi biết nếu tôi cần làm rõ bất kỳ điều gì.

Câu hỏi Stack Overflow duy nhất với bất kỳ điểm tương đồng nào là this, nhưng không liên quan đến vấn đề của tôi.

Edit: Các mã sau đây được thực hiện trong ứng dụng thử nghiệm WinForms của tôi khi khởi động:

SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(); 

connectionStringBuilder.DataSource = m_DataSource; 
connectionStringBuilder.InitialCatalog = m_InitialCatalog; 
connectionStringBuilder.UserID = m_UserID; 
connectionStringBuilder.Password = m_Password; 
connectionStringBuilder.IntegratedSecurity = false; 
connectionString = connectionStringBuilder.ConnectionString; 

m_DatabaseConnection = new SqlConnection(connectionString); 

Sau đó tôi có 2 nút; một trong số đó gọi SPROC 1 được đề cập ở trên và một cuộc gọi khác gọi là SPROC khác không có cùng sự cố làm chậm. Các mã sau đây được thực hiện trên một trong hai nút bấm (chỉ khác biệt là tên SPROC):

m_DatabaseConnection.Open(); 
m_DatabaseCommand = new SqlCommand("GetCompanies", m_DatabaseConnection); 
m_DatabaseCommand.Parameters.AddWithValue("@StatusID", StatusID); 
m_DatabaseCommand.CommandType = CommandType.StoredProcedure; 
m_DatabaseCommand.CommandTimeout = 0; 

SqlDataAdapter databaseDataAdapter = new SqlDataAdapter(m_DatabaseCommand); 
DataSet databaseDataSet = new DataSet(); 
databaseDataAdapter.Fill(databaseDataSet); 
m_DatabaseConnection.Close(); 
+1

Đây có thể là nội dung hay hơn được đăng trên [dba] (http://dba.stackexchange.com/). – Oded

+1

Điều này phải do mã của bạn. Tuy nhiên, vì bạn chưa cho chúng tôi thấy mã của bạn, chúng tôi sẽ không thể giúp bạn. –

+0

@JohnSaunders - Tôi có thể đăng truy vấn cho SPROC 1 nếu muốn, nhưng tôi không nghĩ ai sẽ được hưởng lợi từ dòng 1600+ SPROC 2. – njb

Trả lời

3

Dưới đây là ý tưởng của tôi để gỡ lỗi vấn đề này:

  • Hãy thử gọi SqlConnection.ClearAllPools() Sau khi xử lý các kết nối. Nếu điều này khắc phục được sự cố, sự cố được liên kết với một kết nối cụ thể.
  • Tiếp theo, kèm theo SPROC trong giao dịch rõ ràng.
  • Tiếp theo, hãy gọi SqlConnection.ClearAllPools() trước khi gọi SPROC.
  • SPROC trả lại bao nhiêu dữ liệu?
  • Vui lòng đăng mã C# bạn đang sử dụng để mở kết nối và thực thi SPROC.
  • Tạo ứng dụng giao diện điều khiển độc lập đang tái tạo hành vi bạn đang thấy. Điều này sẽ (có thể) chứng minh rằng một cái gì đó trong ứng dụng của bạn là vấn đề bởi vì các ứng dụng giao diện điều khiển sẽ chạy tốt.
+0

Tôi sẽ bắt đầu thử đề xuất của bạn ngay bây giờ, cảm ơn. SPROC 1 trả về 10 bản ghi nhiều nhất, với 11 cột. SPROC 2 trả về 2 bản ghi, với 15 cột. – njb

+0

Gọi ClearAllPools() sau khi Disposing khắc phục được sự cố, cũng như gọi nó trước khi gọi SPROC. Kèm theo SPROC trong một giao dịch rõ ràng (trong đối tượng Net - TransactionScope) cũng sửa lỗi. Nó "hoạt động", nhưng điều gì thực sự gây ra vấn đề? Đây là tất cả được thử nghiệm trong ứng dụng thử nghiệm WinForms độc lập của tôi. – njb

+0

Khi kết nối được trả về vùng, mức cách ly không được đặt lại. Đây có thể là vấn đề. Hãy thử loại bỏ tran, nhưng thực hiện "thiết lập mức độ cô lập giao dịch đọc cam kết" trước khi thực hiện proc. Điều này có khắc phục được sự cố không? – usr

Các vấn đề liên quan