【发布时间】:2011-02-19 03:02:15
【问题描述】:
我有一个在现有 VB6 应用程序中硬编码的 sql 语句。我正在升级 C# 中的新版本并使用 Linq To Sql。我能够让 LinqToSql 生成相同的 sql(在我开始重构之前),但由于某种原因,LinqToSql 生成的 Sql 比原始 sql 慢 5x。 这是在 LinqPad 中直接运行生成的 Sql。
我那微弱的 sql 眼睛能发现的唯一真正区别是 WITH (NOLOCK),如果我添加到 LinqToSql 生成的 sql 中,没有任何区别。
有人可以指出我在这里做错了什么吗?谢谢!
现有的硬编码 Sql(5.0 秒)
SELECT DISTINCT
CH.ClaimNum, CH.AcnProvID, CH.AcnPatID, CH.TinNum, CH.Diag1, CH.GroupNum, CH.AllowedTotal
FROM Claims.dbo.T_ClaimsHeader AS CH WITH (NOLOCK)
WHERE
CH.ContractID IN ('123A','123B','123C','123D','123E','123F','123G','123H')
AND ( ( (CH.Transmited Is Null or CH.Transmited = '')
AND CH.DateTransmit Is Null
AND CH.EobDate Is Null
AND CH.ProcessFlag IN ('Y','E')
AND CH.DataSource NOT IN ('A','EC','EU')
AND CH.AllowedTotal > 0 ) )
ORDER BY CH.AcnPatID, CH.ClaimNum
从 LinqToSql 生成的 Sql(27.6 秒)
-- Region Parameters
DECLARE @p0 NVarChar(4) SET @p0 = '123A'
DECLARE @p1 NVarChar(4) SET @p1 = '123B'
DECLARE @p2 NVarChar(4) SET @p2 = '123C'
DECLARE @p3 NVarChar(4) SET @p3 = '123D'
DECLARE @p4 NVarChar(4) SET @p4 = '123E'
DECLARE @p5 NVarChar(4) SET @p5 = '123F'
DECLARE @p6 NVarChar(4) SET @p6 = '123G'
DECLARE @p7 NVarChar(4) SET @p7 = '123H'
DECLARE @p8 VarChar(1) SET @p8 = ''
DECLARE @p9 NVarChar(1) SET @p9 = 'Y'
DECLARE @p10 NVarChar(1) SET @p10 = 'E'
DECLARE @p11 NVarChar(1) SET @p11 = 'A'
DECLARE @p12 NVarChar(2) SET @p12 = 'EC'
DECLARE @p13 NVarChar(2) SET @p13 = 'EU'
DECLARE @p14 Decimal(5,4) SET @p14 = 0
-- EndRegion
SELECT DISTINCT
[t0].[ClaimNum],
[t0].[acnprovid] AS [AcnProvID],
[t0].[acnpatid] AS [AcnPatID],
[t0].[tinnum] AS [TinNum],
[t0].[diag1] AS [Diag1],
[t0].[GroupNum],
[t0].[allowedtotal] AS [AllowedTotal]
FROM [Claims].[dbo].[T_ClaimsHeader] AS [t0]
WHERE
([t0].[contractid] IN (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7))
AND (([t0].[Transmited] IS NULL) OR ([t0].[Transmited] = @p8))
AND ([t0].[DATETRANSMIT] IS NULL)
AND ([t0].[EOBDATE] IS NULL)
AND ([t0].[PROCESSFLAG] IN (@p9, @p10))
AND (NOT ([t0].[DataSource] IN (@p11, @p12, @p13)))
AND ([t0].[allowedtotal] > @p14)
ORDER BY [t0].[acnpatid], [t0].[ClaimNum]
新的 LinqToSql 代码(30 多秒...超时)
var contractIds = T_ContractDatas.Where(x => x.EdiSubmissionGroupID == "123-01").Select(x => x.CONTRACTID).ToList();
var processFlags = new List<string> {"Y","E"};
var dataSource = new List<string> {"A","EC","EU"};
var results = (from claims in T_ClaimsHeaders
where contractIds.Contains(claims.contractid)
&& (claims.Transmited == null || claims.Transmited == string.Empty )
&& claims.DATETRANSMIT == null
&& claims.EOBDATE == null
&& processFlags.Contains(claims.PROCESSFLAG)
&& !dataSource.Contains(claims.DataSource)
&& claims.allowedtotal > 0
select new
{
ClaimNum = claims.ClaimNum,
AcnProvID = claims.acnprovid,
AcnPatID = claims.acnpatid,
TinNum = claims.tinnum,
Diag1 = claims.diag1,
GroupNum = claims.GroupNum,
AllowedTotal = claims.allowedtotal
}).OrderBy(x => x.ClaimNum).OrderBy(x => x.AcnPatID).Distinct();
我正在使用上面的常量列表来使 LinqToSql 生成 IN ('xxx','xxx',etc) 否则它会使用同样慢的子查询...
【问题讨论】:
-
查询计划最大的不同似乎是原始sql中ContractId Index seek只占1%,而LinqToSql查询计划占22%。是参数的原因吗?
标签: c# sql linq-to-sql