的响应速度慢查询视图时 - 使用LINQ to SQL

问题描述:

我有以下看法:的响应速度慢查询视图时 - 使用LINQ to SQL

SELECT  
poHeader.No_ AS PONumber, 
poHeader.[Buy-from Vendor No_] AS VendorNumber, 
poHeader.[Document Date] AS DocumentDate, 
vendor.Name AS VendorName, 
vendor.Contact AS VendorContact, 
vendor.[E-Mail] AS VendorEmail, 
vendor.Address AS VendorAddress, 
vendor.[Address 2] AS VendorAddress2, 
vendor.City AS VendorCity, 
vendor.County AS VendorCounty, 
vendor.[Post Code] AS VendorPostCode, 
vendor.[Phone No_] AS VendorPhone, 
vendor.[Fax No_] AS VendorFax, 
salesHeader.No_ AS SONumber, 
poHeader.[Order Date] AS OrderDate, 
salesHeader.[Crocus Comment] AS CrocusComment, 
salesHeader.GiftMessage, 
salesHeader.[Delivery Comment] AS DeliveryComment, 
salesHeader.[Shipment Date] AS DeliveryDate, 
COALESCE (salesHeader.[Ship-to Name], 
poHeader.[Ship-to Name]) AS DeliveryName, 
COALESCE (salesHeader.[Ship-to Address], 
poHeader.[Ship-to Address]) AS DeliveryAddress, 
COALESCE (salesHeader.[Ship-to Address 2], 
poHeader.[Ship-to Address 2]) AS DeliveryAddress2, 
COALESCE (salesHeader.[Ship-to City], 
poHeader.[Ship-to City]) AS DeliveryCity, COALESCE (salesHeader.[Ship-to County], 
poHeader.[Ship-to County]) AS DeliveryCounty, 
COALESCE (salesHeader.[Ship-to Post Code], 
poHeader.[Ship-to Post Code]) AS DeliveryPostcode, 
salesHeader.DeliveryPhoneNo, poForEmailing.Processed, 
poForEmailing.Copied 

FROM   
Navision4.dbo.[Crocus Live$Purch_ orders for e-mailing] AS poForEmailing 
LEFT OUTER JOIN 
Navision4.dbo.[Crocus Live$Purchase Header] AS poHeader ON poForEmailing.No_ = poHeader.No_ 
INNER JOIN 
Navision4.dbo.[Crocus Live$Vendor] AS vendor ON poHeader.[Buy-from Vendor No_] = vendor.No_ 
LEFT OUTER JOIN 
Navision4.dbo.[Crocus Live$Sales Header] AS salesHeader ON salesHeader.No_ = dbo.fnGetSalesOrderNumber(poHeader.No_) 

这种观点是在一个名为NavisionMeta 数据库中创建它查询数据库(在同一台服务器上)claled Navision4

我最近将两个数据库都移到了新的(更好的)硬件上。 不知道这是相关的,但新的硬件具有SQL 2008,和旧的硬件中运行SQL 2000

如果我使用SQL Management Studio中此查询需要2分钟以上进行查询:

SELECT * 
FROM [NavisionMeta].[dbo].[PurchaseOrders] 
WHERE Processed=0 AND Copied=0 

这太久呀!

即使我将超时时间调整为5分钟,LINQ中的以下查询将全部放在一起超时!

  var purchaseOrdersNotProcessed = (from p in db.PurchaseOrders 
               where p.Copied.Equals(0) 
               && p.Processed.Equals(0) 
               select p).ToList(); 

什么令我困惑的是,在以前的硬件上,它工作的很好!

以防万一它是相关的,上面所用的UDF是:

CREATE FUNCTION [dbo].[fnGetSalesOrderNumber](@PONumber varchar(20)) 
RETURNS varchar(20) 
AS 
BEGIN 

RETURN (
SELECT 
    TOP 1 [Sales Order No_] 
FROM 
    Navision4.dbo.[Crocus Live$Purchase Line] 
WHERE 
    [Document No_] = @PONumber 
) 
+0

您是否也传播了索引,或者只是表结构和数据?你是否查看过查看查询本身的执行计划,看看它是如何执行的?我想知道为什么查询在服务器上很慢,然后我担心LINQ部分。 – tvanfosson 2010-01-08 13:33:39

一个起点,可能是看旧机和新机无论在查询的执行计划。新版本的SQL Server肯定会存在优化差异。执行计划可能会告诉你,索引是必要的,由于某种原因,在以前的版本中并不重要。

+0

好的,谢谢...我该怎么做? (我以前没有这样做,对不起!) – Alex 2010-01-08 13:33:30

+0

在SSMS中运行查询之前,单击“显示实际执行计划”(悬停在上以查看它们是什么)的图标。 – tvanfosson 2010-01-08 13:35:44

+0

我已经做了这个...但我不知道该怎么做 - http://twitpic.com/x77ig/full (这不是新的服务器) 似乎有很高的成本... ? – Alex 2010-01-08 14:11:19

您也可以考虑更新统计信息。

编辑

我不知道你正在尝试做的,但如果你试图让PO的信息,我认为下面的变化会有所帮助,你有

FROM Navision4.dbo.[Crocus Live$Purch_ orders for e-mailing] AS poForEmailing 
    LEFT OUTER JOIN Navision4.dbo.[Crocus Live$Purchase Header] AS poHeader ON poForEmailing.No_ = poHeader.No_ 
    INNER JOIN Navision4.dbo.[Crocus Live$Vendor] AS vendor ON poHeader.[Buy-from Vendor No_] = vendor.No_ 
    LEFT OUTER JOIN Navision4.dbo.[Crocus Live$Sales Header] AS salesHeader ON salesHeader.No_ = dbo.fnGetSalesOrderNumber(poHeader.No_) 

试试这个:

FROM Navision4.dbo.[Crocus Live$Purch_ orders for e-mailing] AS poForEmailing 
    LEFT JOIN Navision4.dbo.[Crocus Live$Purchase Header] AS poHeader ON poForEmailing.No_ = poHeader.No_ 
    LEFT JOIN Navision4.dbo.[Crocus Live$Vendor] AS vendor ON poHeader.[Buy-from Vendor No_] = vendor.No_ 
    LEFT JOIN Navision4.dbo.[Crocus Live$Sales Header] AS salesHeader ON salesHeader.No_ = dbo.fnGetSalesOrderNumber(poHeader.No_) 

就速度而言,您可能需要更新一些索引...尤其是No_字段。 除了做如下变更摆脱fuGetSalesOrderNumber()呼吁各行:

;WITH PurchaseLineByPO AS 
(
    SELECT MAX([Sales Order No_]) as SO, [Document No_] as DNum 
    FROM Navision4.dbo.[Crocus Live$Purchase Line] 
    Group By [Document No_] 
) 
--blah blah whole select goes here.. with 
JOIN PurchaseLineByPO ON DNum = poHeader.No_ 
--in the join and 
LEFT OUTER JOIN 
Navision4.dbo.[Crocus Live$Sales Header] AS salesHeader ON salesHeader.No_ = PurchaseLineByPO.SO 
--replaces what you had 

看看是否能为你工作。

忽略低于旧的东西...

这是我很难清楚地看到你在做什么在这里,但它是罕见的外部连接的需要 - 这是真正你想要做什么?如果是这样,您可以反转订单并进行内部连接。例如,你说:

FROM   
Navision4.dbo.[Crocus Live$Purch_ orders for e-mailing] AS poForEmailing 
LEFT OUTER JOIN 
Navision4.dbo.[Crocus Live$Purchase Header] AS poHeader ON poForEmailing.No_ = poHeader.No_ 

,你可以说

FROM   
Navision4.dbo.[Crocus Live$Purchase Header] AS poHeader 
LEFT INNER JOIN 
Navision4.dbo.[Crocus Live$Purch_ orders for e-mailing] AS poForEmailing ON poForEmailing.No_ = poHeader.No_ 

根据您的数据,这可能会对你的运行时间显著影响。

+0

当我在SSMS中这样做时,我在加入时遇到错误 – Alex 2010-01-10 14:26:00

Left Inner Join?嗯,不知道这是否会有所帮助...

如果此查询以前工作(数据不是性能),那么上述查询将受益于将所有联接转换为INNER JOINs。因为你是INNER JOINing一个来自poHeader(外连接)的值的供应商,所以你基本上在poHeader上做了一个内连接要求(除了外连接可能遇到性能问题外)。供应商无法返回值,除非poHeader具有值,并且由于供应商是内连接的,如果poHeader中没有值,整行将被忽略。与salesHeader一样。在连接中使用的函数需要poHeader中的一个值(必须根据上述逻辑具有一个值),所以这个连接也可以从显式的INNER JOIN中获益,而不仅仅是一个隐含的连接。

除此之外,我的确同意关于索引的说法(除了关于很少需要的外部连接的说法外,就像说如果你有一把锤子,你不需要一把螺丝刀)。索引听起来是对性能较弱的最合理的解释。具体来说,你应该检查你的poForEmailing别名表是否有索引([processed],[copied])。如果没有该索引,则可以预期查询时间至少翻倍,因为数据大小加倍,因为该表中的每条记录都需要针对这些谓词进行测试。关于你原来的问题,我没有注意到SQL Server 2008中的任何东西都会提示性能发生这样的变化,所有其他事情都是平等的。