2011-04-05 95 views
7

当然,一切都是相对的,但与使用查询管理器简单执行相同的SQL相比,存在很大差异。调用存储过程的LINQ很慢

我已经使用探查器来查看LINQ调用存储过程时数据库执行的SQL语句。如果我复制/粘贴SQL并通过查询管理器运行完全相同的SQL,结果将在大约1400毫秒内返回,结果将在2毫秒内返回。这让我想知道我是否有需要做的事情?这里有人有过类似的经历吗?

以下是从SQL LINQ派:

declare @p26 int 
set @p26=0 
exec sp_executesql N'EXEC @RETURN_VALUE = [dbo].[TapeInfo_Get] @TapeFlag_IsDigitized = @p0, @TapeFlag_ChosenSingleTape = @p1, @TapeFlag_ChosenHierarchy = @p2, @TapeFlag_ChosenForced = @p3, @TapeFlag_ExcludedHierarchy = @p4, @TapeFlag_ExcludedARKBNR = @p5, @TapeFlag_ExcludedForced = @p6, @TapeFlag_ExcludedFilmRoll = @p7, @TapeFlag_ExcludedDVCPRO = @p8, @TapeFlag_ExcludedVHS = @p9, @TapeFlag_ExcludedType = @p10, @TapeFlag_NoticeBNR = @p11, @TapeFlag_NoticeMultiplePNR = @p12, @TapeFlag_NoticeType = @p13, @ProductionFlag_ExcudedDate = @p14, @ProductionFlag_NoticeMultipleTape = @p15, @ProductionFlag_NoticeFilm1C = @p16, @ProductionFlag_NoticeFilmBetaDigial = @p17, @ProductionFlag_ExcludedForeignProd = @p18, @Query = @p19, @PageIndex = @p20, @PageSize = @p21, @ReturnCount = @p22',N'@p0 bit,@p1 bit,@p2 bit,@p3 bit,@p4 bit,@p5 bit,@p6 bit,@p7 bit,@p8 bit,@p9 bit,@p10 bit,@p11 bit,@p12 bit,@p13 bit,@p14 bit,@p15 bit,@p16 bit,@p17 bit,@p18 bit,@p19 varchar(8000),@p20 int,@p21 int,@p22 bit,@RETURN_VALUE int output',@p0=0,@p1=1,@p2=1,@p3=1,@p4=0,@p5=0,@p6=0,@p7=0,@p8=0,@p9=0,@p10=0,@p11=0,@p12=0,@p13=0,@p14=0,@p15=0,@p16=0,@p17=0,@p18=0,@p19=NULL,@p20=0,@p21=10,@p22=0,@[email protected] output 
select @p26 

在.NET的C#代码很简单:

using(BRSDataContext dc = new BRSDataContext()) 
{ 
    dc.TapeInfo_Get(false, false, false, false, false, false, false, false, false, false, false, null, true, null, false, null, null, null, false, query, startRowIndex, count, false) 
} 

有我丢失的东西?任何想法如何戏剧性地影响表现? 数据库(MSSQL 2008)和托管执行LINQ的asp.net站点的网络服务器位于同一网络上,并且都运行Windows Server 2008 std 32bit。

感谢您的帮助。

SOLUTION

SET ARITHABORT ON; 

所以它不是一个LINQ的问题,但更多的是普通的SQL Server的问题。

+2

你最先执行哪一个? SSMS或应用程序?在两种查询方法之间切换时,您可以重复生成相同的性能结果吗?你究竟在哪里得到你引用的指标? – 2011-04-05 15:11:00

+0

@Pete M,感谢您的回复,我先通过LINQ调用,然后将SQL复制到Query Manager中并执行它。但是,即使在第一次调用之后,结果仍然与LINQ保持一致。测量数据来自Profiler,SQL Server 2008一起发布。 – 2011-04-05 15:14:05

+0

Bummer,我希望这将成为一个执行计划问题......要明确一点,您看到完全在SQL Server中执行1400毫秒的时间?如在,不包括运输/演示/其他?你有LINQPad吗?我会尝试引用你的DataContext并在你的应用程序的上下文之外运行查询,看看你是否得到相同的结果。真的很奇怪,看到服务器端完全不同,并且一直存在多个命中,存储过程不会少于... – 2011-04-05 16:17:38

回答

8

设置arithabort;只是为了测试它。有几个建议的方法来解决这个问题。一种是在存储过程中添加“with recompile”。但我通常不使用的输入参数,解决它直接

例如:

create stored procedure foo(@ParamUserId int) 
as 
    declare @UserId int 
    set @UserId = @ParamUserId 

    select * from Users where UserId = @UserId 

或者类似的东西。

这里对此事http://www.simple-talk.com/sql/t-sql-programming/parameter-sniffing/

+0

非常感谢,非常有帮助。 – 2011-04-06 16:43:34

+1

很高兴能有所帮助。我记得这一整天都在挠头。本来很高兴知道当时的stackoverflow :) – ingo 2011-04-08 00:38:52

+0

伟大的链接到一些广泛的研究到这个问题,但有这么多,你需要A)至少一个小时通读和消化它或B)15或20几分钟浏览它并尝试找到可帮助您解决问题的部分。我采用了后一种方法,但即使在运行sp_recompile(上面链接的作者说可能的情况)后,问题也会重现。在我的情况下,最终解决了我的问题是将我传递给我的sproc的datetime参数换成varchar参数(然后我将它们转换为sproc中的datetime)。 – Jagd 2013-06-20 20:30:10

2

这里的好文章是C#中的LINQ to ARITHABORT上设置;

System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(myConnectionString); 
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("set arithabort on;", conn); 
command.Connection.Open(); 
command.ExecuteNonQuery(); 
CMyDataContext myDataContext = new CMyDataContext(conn);