我有以下观点:
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 :(得分:1)
您也可以考虑更新统计信息。
答案 1 :(得分:1)
左内加入?嗯,不确定这是否会有所帮助......
如果此查询之前有效(数据不是性能),则上述查询将从将所有连接转换为INNER JOIN中受益。因为你是来自poHeader(外连接)的值的INNER JOINing供应商,所以你基本上也在poHeader上建立了一个内连接要求(除了外连接的潜在性能命中)。除非poHeader具有值,并且供应商是内连接的,否则供应商不能返回值,如果poHeader中没有值,则将忽略整行。与salesHeader相同。连接中使用的函数需要poHeader中的值(必须具有根据上述逻辑的值),因此此连接也可以从显式的INNER JOIN中获益,而不仅仅是隐含的连接。
除此之外,我同意关于索引的陈述(除了关于外连接的陈述很少。这就像说如果你有锤子你不需要螺丝刀)。索引听起来像是对性能较弱的最合乎逻辑的解释。具体来说,您应该检查poForEmailing别名表是否有索引([processed],[copied])。如果没有该索引,您可以期望查询时间至少加倍,因为数据大小加倍,因为该表中的每个记录都需要针对这些谓词进行测试。关于你原来的问题,我没有注意到SQL Server 2008中任何表明性能发生这种变化的东西,其他条件都相同。
答案 2 :(得分:0)
一个起点可能是在旧机器和新机器上查看查询的执行计划。对于较新版本的SQL Server,肯定存在优化差异。执行计划可能会向您显示索引是必要的,由于某种原因,索引在先前版本中并不那么重要。
答案 3 :(得分:0)
修改强>
我不确定你要做什么,但如果你想获得有关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
看看它是否适合你。
忽略下面的旧内容......
我很难确切地看到你在这里做了什么,但是很少需要OUTER连接 - 这实际上是你想做什么的?如果是,您可以撤消订单并进行内部联接。例如,你说:
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_
根据您的数据,这可能会对您的运行时间产生重大影响。