2013-02-27 45 views
7

Tôi có một thủ tục được lưu trữ mà tôi đang gọi bằng cách sử dụng LinqToSQL. Tôi không làm gì đặc biệt chút nào, ví dụLINQ Lưu trữ thủ tục Timeout nhưng SSMS nhanh

MyDataContext db = new MyDataContext() 

var results = db.storedProcedure(param1, param2, param3) 

// Do stuff 

Khi tôi chạy quy trình đã lưu bằng cách sử dụng cùng một thông số chính xác, tôi nhận được kết quả từ 2 đến 6 giây. Cơ sở dữ liệu là một cơ sở dữ liệu từ xa.

Tuy nhiên, khi tôi chạy thủ tục được lưu trữ phải mất (sau khi gỡ lỗi ....) 275 giây! Trong những trường hợp bình thường này mang đến cho các ngoại lệ sau đây:

[Win32Exception (0x80004005): Các hoạt động chờ đợi timed out]

[SqlException (0x80131904): Timeout hết hạn. Khoảng thời gian chờ trôi qua trước khi hoàn thành thao tác hoặc máy chủ không phản hồi.] System.Data.SqlClient.SqlConnection.OnError (ngoại lệ SqlException, Boolean breakConnection, Hành động 1 wrapCloseInAction) +1753346 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction) +5295154 System.Data.SqlClient.TdsParser .ThrowExceptionAndWarning (TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) 242 System.Data.SqlClient.TdsParser.TryRun (RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader datastream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean & dataReady) 1682 System.Data .SqlClient.SqlDataReader.TryConsumeMetaData() +59 System.Data.SqlClient.SqlDataReader.get_MetaData() +90 System.Data.SqlClient.SqlCommand.Finish ExecuteReader (ds SqlDataReader, RunBehavior runBehavior, String resetOptionsString) 365 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, async Boolean, thời gian chờ Int32, Task & nhiệm vụ, Boolean asyncWrite) 1325 Hệ thống .Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, phương thức String, hoàn thành TaskCompletionSource`1, Int32 timeout, Task & tác vụ, Boolean asyncWrite) +175 System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +53 System.Data.SqlClient.SqlCommand.ExecuteReader (Hành vi CommandBehavior, String method) +134 System.Data.SqlClie nt.SqlCommand.ExecuteDbDataReader (Hành vi CommandBehavior) +41 System.Data.Common.DbCommand.ExecuteReader() +12 System.Data.Linq.SqlClient.SqlProvider.Execute (truy vấn biểu thức, QueryInfo queryInfo, nhà máy IObjectReaderFactory, Object [] parentArgs, Object [] userArgs, ICompiledSubQuery [] subQueries, Object lastResult) +1306 System.Data.Linq.SqlClient.SqlProvider.ExecuteAll (truy vấn biểu thức, QueryInfo [] queryInfos, IObjectReaderFactory factory, Object [] userArguments, ICompiledSubQuery [] subQueries) +118 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute (truy vấn biểu thức) +342 System.Data.Linq.DataContext.ExecuteMethodCall (Ví dụ đối tượng, MethodInfo methodInfo, Object [] thông số) +83

Tất cả các thủ tục được lưu trữ khác được gọi theo cùng một cách, nhưng không có sự cố nào xảy ra. Quản trị viên DB từ xa cho biết anh ta có thể thấy bắt đầu và kết thúc cuộc gọi trước khi thời gian chờ xảy ra, do đó, dường như điều gì đó liên quan đến các bước SAU LINQ nhận dữ liệu.

Có ai đã từng trải nghiệm điều này trước đây và bất kỳ ý tưởng nào về cách khắc phục sự cố không?

Tôi đã thử xóa SP khỏi tệp dmbl và thêm lại.Nó nhận thấy một sự thay đổi trong một trong các giá trị từ thập phân đến gấp đôi, nhưng ngoài ra tất cả của nó đều giống nhau.

Như mọi khi, hôm qua nó hoạt động tốt!

Xin cảm ơn trước.

Trả lời

3

Ok, cuối cùng tôi đã phát hiện ra câu trả lời REAL cho vấn đề này. SSMS thường sử dụng ARITHABORT ON và mã thường sử dụng ARITHABORT OFF - đây về cơ bản là một tùy chọn để xử lý những gì xảy ra nếu một dòng toán học trong mã có lỗi - ví dụ: chia cho số không.

Điều chính ở đây, là cả hai phương pháp đều có kế hoạch thực hiện khác nhau - đó là lý do tại sao cùng một điều có thể (ngẫu nhiên) mất nhiều thời gian hơn trên trang web so với SSMS.

Kế hoạch thực hiện được biên soạn dựa trên ước tính lần đầu tiên nó được sử dụng để những gì bạn tìm thấy ngẫu nhiên là kế hoạch thực hiện được lưu trữ theo cách khủng khiếp phù hợp với truy vấn đầu tiên của bạn. Đây là những gì đã xảy ra ở đây và nó cũng là lý do tại sao nó đột nhiên bắt đầu hoạt động trở lại - một kế hoạch truy vấn mới được tạo ra sau khi thủ tục lưu sẵn đã được thay đổi.

Cuối cùng, chúng tôi đã sử dụng WITH RECOMPILE trong quy trình được lưu trữ - vì vậy không có sử dụng lại hiệu quả kế hoạch thực hiện, nhưng chúng tôi đã không nhận thấy bất kỳ sự khác biệt nào và vấn đề vẫn chưa xảy ra.

0

Điều gì gây ra sự cố này cho tôi là một vòng lặp dựa trên Linq.Table < > .Count(). Trên môi trường phát triển, truy vấn cơ bản là gần như ngay lập tức, nhưng trong quá trình sản xuất nó mất một vài giây. Hooking lên SQL Profiler tiết lộ rằng truy vấn được thực hiện với mỗi lần lặp của vòng lặp, do đó, những "vài giây" bắt đầu thêm lên, và cuối cùng hết thời gian chờ.

Giải pháp cho tôi là gán kết quả Count() cho một biến cục bộ và sử dụng nó trong vòng lặp, để Count() không thực hiện lại truy vấn với mỗi lần lặp. Tôi tưởng tượng người khác sẽ gặp phải vấn đề này nếu họ dựa vào các hàm tổng hợp LINQ tích hợp sẽ thực thi lại các truy vấn chậm.

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