c# - LINQ query slow, creates Timeout; generated SQL is fine? -


i have complex linq query slow, creates system.data.sqlclient.sqlexception: "the wait operation timed out".

however, when log generated sql (by assigning textwriter datacontext's log), , execute directly on sql server, completes in 4 seconds, fine.

where discrepancy come , how debug it?

edit: i've noticed in sql server management studio's activity monitor processor time spiking 100% when query executing .net, 3% or when execute generated sql query.

i'm not sure how posting code help, since requested, here code containing query:

var db = myproject.getdatacontext(); var statuspaymentsuccess = new string[] { "success", "rembours", "afterpay" };  var items = db.orders.where(item =>     (siteid == null || item.siteid == siteid) &&     (ls_list.contains(item.orderorderlifecycles.orderbydescending(it => it.id).first().orderlifecycleid)) &&     (item.orderorderpaymentstatus.any(ops => statuspaymentsuccess.contains(ops.orderpaymentstatus.code)) &&         (cycleid == null || item.orderorderlifecycles.first().orderlifecycleid == cycleid) &&         (locationid == null || item.salelocationid == locationid) &&         (string.isnullorempty(salesperson) || item.employeename.tolower() == salesperson.tolower())) );  var betweenorders = items.select(it => new orderbetween() {     firstpaydate = it.orderorderpaymentstatus.firstordefault(ops => statuspaymentsuccess.contains(ops.orderpaymentstatus.code)).datetime,     ordertotal = it.totalamount,     vattotal = it.orderitems.sum(it2 => it2.btwamount ?? 0),     quantity = it.orderitems.count,     siteid = it.siteid });  return betweenorders.where(item => item.firstpaydate >= start && item.firstpaydate < stop)     .groupby(item => item.firstpaydate.value.year + "-" + item.firstpaydate.value.month).select(         item =>             new saletotal()             {                 count = item.sum(sub => sub.quantity),                 month = item.firstordefault().firstpaydate.value.year + "-" + item.firstordefault().firstpaydate.value.month.tostring().padleft(2, '0'),                 total = item.sum(sub => sub.ordertotal),                 vat = item.sum(sub => sub.vattotal)             }).orderby(item => item.month).toarray(); 

where ls_list list<int> containing orderorderlifecycles ids.

the generated sql query pulled log:

declare @p0 nvarchar(4000) = 'success'  declare @p1 nvarchar(4000) = 'rembours'  declare @p2 nvarchar(4000) = 'afterpay'  declare @p3 decimal(31,2) = '0'  declare @p4 nvarchar(4000) = '-'  declare @p5 datetime = '2016-06-01'  declare @p6 datetime = '2016-09-01'  declare @p7 int = '4'  declare @p8 int = '5'  declare @p9 int = '8'  declare @p10 nvarchar(4000) = 'success'  declare @p11 nvarchar(4000) = 'rembours'  declare @p12 nvarchar(4000) = 'afterpay'  declare @p13 nvarchar(4000) = '-'  declare @p14 nvarchar(4000) = '-'  declare @p15 int = '2'  declare @p16 nchar(1) = '0'  select [t64].[value] [month], [t64].[value2] [count], [t64].[value22] [total], [t64].[value3] [vat] (     select ((convert(nvarchar,datepart(year, (         select [t23].[value]         (             select top (1) [t18].[value]             (                 select (                     select [t17].[datetime]                     (                         select top (1) [t15].[datetime]                         [dbo].[orderorderpaymentstatus] [t15]                         inner join [dbo].[orderpaymentstatus] [t16] on [t16].[id] = [t15].[orderpaymentstatusid]                         ([t16].[code] in (@p0, @p1, @p2)) , ([t15].[orderid] = [t14].[id])                         ) [t17]                     ) [value], [t14].[id]                 [dbo].[order] [t14]                 ) [t18]             ((([t13].[value4] null) , ((((convert(nvarchar,datepart(year, [t18].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t18].[value])))) null)) or (([t13].[value4] not null) , ((((convert(nvarchar,datepart(year, [t18].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t18].[value])))) not null) , ([t13].[value4] = (((convert(nvarchar,datepart(year, [t18].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t18].[value]))))))) , ([t18].[value] >= @p5) , ([t18].[value] < @p6) , (((                 select [t20].[orderlifecycleid]                 (                     select top (1) [t19].[orderlifecycleid]                     [dbo].[orderorderlifecycle] [t19]                     [t19].[orderid] = [t18].[id]                     order [t19].[id] desc                     ) [t20]                 )) in (@p7, @p8, @p9)) , (exists(                 select null [empty]                 [dbo].[orderorderpaymentstatus] [t21]                 inner join [dbo].[orderpaymentstatus] [t22] on [t22].[id] = [t21].[orderpaymentstatusid]                 ([t22].[code] in (@p10, @p11, @p12)) , ([t21].[orderid] = [t18].[id])                 ))             ) [t23]         )))) + @p14) + (         (case              when (convert(int,datalength(convert(nvarchar,datepart(month, (                 select [t63].[value]                 (                     select top (1) [t58].[value]                     (                         select (                             select [t57].[datetime]                             (                                 select top (1) [t55].[datetime]                                 [dbo].[orderorderpaymentstatus] [t55]                                 inner join [dbo].[orderpaymentstatus] [t56] on [t56].[id] = [t55].[orderpaymentstatusid]                                 ([t56].[code] in (@p0, @p1, @p2)) , ([t55].[orderid] = [t54].[id])                                 ) [t57]                             ) [value], [t54].[id]                         [dbo].[order] [t54]                         ) [t58]                     ((([t13].[value4] null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) null)) or (([t13].[value4] not null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) not null) , ([t13].[value4] = (((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value]))))))) , ([t58].[value] >= @p5) , ([t58].[value] < @p6) , (((                         select [t60].[orderlifecycleid]                         (                             select top (1) [t59].[orderlifecycleid]                             [dbo].[orderorderlifecycle] [t59]                             [t59].[orderid] = [t58].[id]                             order [t59].[id] desc                             ) [t60]                         )) in (@p7, @p8, @p9)) , (exists(                         select null [empty]                         [dbo].[orderorderpaymentstatus] [t61]                         inner join [dbo].[orderpaymentstatus] [t62] on [t62].[id] = [t61].[orderpaymentstatusid]                         ([t62].[code] in (@p10, @p11, @p12)) , ([t61].[orderid] = [t58].[id])                         ))                     ) [t63]                 )))) / 2)) >= @p15 convert(nvarchar,datepart(month, (                 select [t63].[value]                 (                     select top (1) [t58].[value]                     (                         select (                             select [t57].[datetime]                             (                                 select top (1) [t55].[datetime]                                 [dbo].[orderorderpaymentstatus] [t55]                                 inner join [dbo].[orderpaymentstatus] [t56] on [t56].[id] = [t55].[orderpaymentstatusid]                                 ([t56].[code] in (@p0, @p1, @p2)) , ([t55].[orderid] = [t54].[id])                                 ) [t57]                             ) [value], [t54].[id]                         [dbo].[order] [t54]                         ) [t58]                     ((([t13].[value4] null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) null)) or (([t13].[value4] not null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) not null) , ([t13].[value4] = (((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value]))))))) , ([t58].[value] >= @p5) , ([t58].[value] < @p6) , (((                         select [t60].[orderlifecycleid]                         (                             select top (1) [t59].[orderlifecycleid]                             [dbo].[orderorderlifecycle] [t59]                             [t59].[orderid] = [t58].[id]                             order [t59].[id] desc                             ) [t60]                         )) in (@p7, @p8, @p9)) , (exists(                         select null [empty]                         [dbo].[orderorderpaymentstatus] [t61]                         inner join [dbo].[orderpaymentstatus] [t62] on [t62].[id] = [t61].[orderpaymentstatusid]                         ([t62].[code] in (@p10, @p11, @p12)) , ([t61].[orderid] = [t58].[id])                         ))                     ) [t63]                 )))             else replicate(@p16, @p15 - (convert(int,datalength(convert(nvarchar,datepart(month, (                 select [t63].[value]                 (                     select top (1) [t58].[value]                     (                         select (                             select [t57].[datetime]                             (                                 select top (1) [t55].[datetime]                                 [dbo].[orderorderpaymentstatus] [t55]                                 inner join [dbo].[orderpaymentstatus] [t56] on [t56].[id] = [t55].[orderpaymentstatusid]                                 ([t56].[code] in (@p0, @p1, @p2)) , ([t55].[orderid] = [t54].[id])                                 ) [t57]                             ) [value], [t54].[id]                         [dbo].[order] [t54]                         ) [t58]                     ((([t13].[value4] null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) null)) or (([t13].[value4] not null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) not null) , ([t13].[value4] = (((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value]))))))) , ([t58].[value] >= @p5) , ([t58].[value] < @p6) , (((                         select [t60].[orderlifecycleid]                         (                             select top (1) [t59].[orderlifecycleid]                             [dbo].[orderorderlifecycle] [t59]                             [t59].[orderid] = [t58].[id]                             order [t59].[id] desc                             ) [t60]                         )) in (@p7, @p8, @p9)) , (exists(                         select null [empty]                         [dbo].[orderorderpaymentstatus] [t61]                         inner join [dbo].[orderpaymentstatus] [t62] on [t62].[id] = [t61].[orderpaymentstatusid]                         ([t62].[code] in (@p10, @p11, @p12)) , ([t61].[orderid] = [t58].[id])                         ))                     ) [t63]                 )))) / 2))) + (convert(nvarchar,datepart(month, (                 select [t63].[value]                 (                     select top (1) [t58].[value]                     (                         select (                             select [t57].[datetime]                             (                                 select top (1) [t55].[datetime]                                 [dbo].[orderorderpaymentstatus] [t55]                                 inner join [dbo].[orderpaymentstatus] [t56] on [t56].[id] = [t55].[orderpaymentstatusid]                                 ([t56].[code] in (@p0, @p1, @p2)) , ([t55].[orderid] = [t54].[id])                                 ) [t57]                             ) [value], [t54].[id]                         [dbo].[order] [t54]                         ) [t58]                     ((([t13].[value4] null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) null)) or (([t13].[value4] not null) , ((((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value])))) not null) , ([t13].[value4] = (((convert(nvarchar,datepart(year, [t58].[value]))) + @p13) + (convert(nvarchar,datepart(month, [t58].[value]))))))) , ([t58].[value] >= @p5) , ([t58].[value] < @p6) , (((                         select [t60].[orderlifecycleid]                         (                             select top (1) [t59].[orderlifecycleid]                             [dbo].[orderorderlifecycle] [t59]                             [t59].[orderid] = [t58].[id]                             order [t59].[id] desc                             ) [t60]                         )) in (@p7, @p8, @p9)) , (exists(                         select null [empty]                         [dbo].[orderorderpaymentstatus] [t61]                         inner join [dbo].[orderpaymentstatus] [t62] on [t62].[id] = [t61].[orderpaymentstatusid]                         ([t62].[code] in (@p10, @p11, @p12)) , ([t61].[orderid] = [t58].[id])                         ))                     ) [t63]                 ))))          end)) [value], [t13].[value] [value2], [t13].[value2] [value22], [t13].[value3]     (         select sum([t8].[value3]) [value], sum([t8].[totalamount]) [value2], sum([t8].[value22]) [value3], [t8].[value] [value4]         (             select ((convert(nvarchar,datepart(year, [t7].[value]))) + @p4) + (convert(nvarchar,datepart(month, [t7].[value]))) [value], [t7].[value] [value2], [t7].[id], [t7].[value3], [t7].[totalamount], [t7].[value2] [value22]             (                 select (                     select [t3].[datetime]                     (                         select top (1) [t1].[datetime]                         [dbo].[orderorderpaymentstatus] [t1]                         inner join [dbo].[orderpaymentstatus] [t2] on [t2].[id] = [t1].[orderpaymentstatusid]                         ([t2].[code] in (@p0, @p1, @p2)) , ([t1].[orderid] = [t0].[id])                         ) [t3]                     ) [value], [t0].[totalamount], (                     select sum([t5].[value])                     (                         select coalesce([t4].[btwamount],@p3) [value], [t4].[orderid]                         [dbo].[orderitem] [t4]                         ) [t5]                     [t5].[orderid] = [t0].[id]                     ) [value2], (                     select count(*)                     [dbo].[orderitem] [t6]                     [t6].[orderid] = [t0].[id]                     ) [value3], [t0].[id]                 [dbo].[order] [t0]                 ) [t7]             ) [t8]         ([t8].[value2] >= @p5) , ([t8].[value2] < @p6) , (((             select [t10].[orderlifecycleid]             (                 select top (1) [t9].[orderlifecycleid]                 [dbo].[orderorderlifecycle] [t9]                 [t9].[orderid] = [t8].[id]                 order [t9].[id] desc                 ) [t10]             )) in (@p7, @p8, @p9)) , (exists(             select null [empty]             [dbo].[orderorderpaymentstatus] [t11]             inner join [dbo].[orderpaymentstatus] [t12] on [t12].[id] = [t11].[orderpaymentstatusid]             ([t12].[code] in (@p10, @p11, @p12)) , ([t11].[orderid] = [t8].[id])             ))         group [t8].[value]         ) [t13]     ) [t64] order [t64].[value] 

one obvious way improve query catches eye in first part:

var items = db.orders.where(item =>     (siteid == null || item.siteid == siteid)  && (ls_list.contains(item.orderorderlifecycles.orderbydescending(it => it.id).first().orderlifecycleid))  && (item.orderorderpaymentstatus.any(ops => statuspaymentsuccess.contains(ops.orderpaymentstatus.code))  && (cycleid == null || item.orderorderlifecycles.first().orderlifecycleid == cycleid)  && (locationid == null || item.salelocationid == locationid)  && (string.isnullorempty(salesperson) || item.employeename.tolower() == salesperson.tolower())) ); 

remember whole linq statement translated sql, including these null checks. makes sql query needlessly complex , harder process query optimizer. (by way, show sql query belonging linq statement).

the recommended way deal nullable conditions compose query:

iqueryable<order> items = var items = db.orders;  if(siteid != null) {     items = items.where(item => item.siteid == siteid); } if (cycleid != null) {     items = items.where(item => item.orderorderlifecycles.first().orderlifecycleid == cycleid); } // etc. 

another thing is

item.employeename.tolower() == salesperson.tolower() 

this converts employeename field values before search condition applied it. means index on employeename can't used (also know not sargable). think can remove tolower() calls. in sql query database collation of employeename field used , that's case-insensitive (ci) default.

finally, may consider execute grouping ...

groupby(item => item.firstpaydate.value.year + "-" + item.firstpaydate.value.month) 

... in memory (linq objects) instead of in database. is:

return betweenorders.where(item => item.firstpaydate >= start && item.firstpaydate < stop) .asenumerable() // switch linq objects .groupby(... 

a grouping translated order by (not group by reasons beyond scope of answer) and, again, conversions of database field firstpaydate disables indexes. makes sql query less complex, , it's not heavy operation in memory.


Comments

Popular posts from this blog

Spring Boot + JPA + Hibernate: Unable to locate persister -

go - Golang: panic: runtime error: invalid memory address or nil pointer dereference using bufio.Scanner -

c - double free or corruption (fasttop) -