日期:2014-05-20  浏览次数:20911 次

请问这个linq怎么优化呢?
三张表,分别是OlProduct(在线产品)、SKU和PackageSKU表,其中在线产品表中有个SkuId(对应SKU表的ID但没有主外键)和一个Sku字符串;PackageSKU为套餐表,里面的字段有一个FSKUId(主SKUId,对应SKU表的ID,有主外键),CSKUId(子SKUId,对应SKU表的ID,有主外键)和Count(数量);而SKU表里面也有个Sku字符串。现在的需求是按Sku字符串搜索,符合条件的为:在线产品表里面的Sku字符串、Sku表里面的Sku字符串、同时如果是主(子)Sku的,那么将其子(主)Sku也搜出来,现在写的linq是:

query = from p in db.OlProduct
        join sku in db.SKU.DefaultIfEmpty() on p.SkuID equals sku.Id into pSku
        from pg in pSku.DefaultIfEmpty()
        where
            p.SKU.Contains(strSearchWord) ||
            pg.PackageSKU.Any(g => g.SKU1.SKU1.Contains(strSearchWord)) ||
            pg.PackageSKU1.Any(g => g.SKU.SKU1.Contains(strSearchWord)) ||
            pg.SKU1.Contains(strSearchWord)
        select p;

这样写的话生成的sql语句为:

SELECT *
FROM [dbo].[OlProduct] AS [t0]
LEFT OUTER JOIN ((
        SELECT NULL AS [EMPTY]
        ) AS [t1]
    LEFT OUTER JOIN [dbo].[SKU] AS [t2] ON 1=1 ) ON [t0].[SkuID] = ([t2].[Id])
WHERE (([t0].[SKU] LIKE @p0) OR (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [dbo].[PackageSKU] AS [t3]
    INNER JOIN [dbo].[SKU] AS [t4] ON [t4].[Id] = [t3].[FSKUId]
    WHERE ([t4].[SKU] LIKE @p1) AND ([t3].[CSKUId] = [t2].[Id])
    )) OR (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [dbo].[PackageSKU] AS [t5]
    INNER JOIN [dbo].[SKU] AS [t6] ON [t6].[Id] = [t5].[CSKUId]
    WHERE ([t6].[SKU] LIKE @p2) AND ([t5].[FSKUId] = [t2].[Id])
    )) OR ([t2].[SKU] LIKE @p3)) AND ([t0].[Cid] = @p4) AND ([t0].[EbayOnlineStatus] = @p5)
ORDER BY [t0].[Id] DESC

搜索的速度要十几秒非常慢,请问这个linq要改进的话该如何改进呢?

------解决方案--------------------
1. 为 SKU  SKU1 等列添加索引
2.  
query = from p in db.OlProduct
        join sku in db.SKU on p.SkuID equals sku.Id into pSku
        from pg in pSku.DefaultIfEmpty()
        where
            p.SKU.Contains(strSearchWord) 
------解决方案--------------------

            (pg!=null && pg.PackageSKU.Any(g => g.SKU1.SKU1.Contains(strSearchWord))) 
------解决方案--------------------

            (pg!=null && pg.PackageSKU1.Any(g => g.SKU.SKU1.Contains(strSearchWord))) 
------解决方案--------------------

            (pg!=null && pg.SKU1.Contains(strSearchWord))
        select p;