2010-01-08 3 views
0

je la vue suivante:Réponse lente lors de l'interrogation vue - 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_) 

Ce point de vue est créé dans une base de données appelée NavisionMeta interroge une base de données (sur le même serveur) claled Navision4

J'ai récemment déplacé les deux bases de données sur un nouveau (meilleur) matériel. Je ne sais pas si cela est pertinent, mais le nouveau matériel a SQL 2008, et l'ancien matériel a été exécutant SQL 2000

Si je fais une recherche à l'aide de cette requête dans SQL Management Studio prend plus de 2 minutes:

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

Ce qui est wayyy trop longtemps!

La requête suivante dans LINQ arrive à expiration tous ensemble, même si j'ajuste le délai à 5 minutes! Ce qui me laisse perplexe, c'est que, sur le matériel précédent, cela a bien fonctionné!

Juste au cas où il est pertinent, l'udf utilisé ci-dessus est:

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

Avez-vous également propagé vos index ou simplement la structure et les données de la table? Avez-vous regardé le plan d'exécution de la requête de vue pour voir comment elle est effectuée? Je trouverais pourquoi la requête est lente sur le serveur avant que je m'inquiète de la partie LINQ. – tvanfosson

Répondre

0

Un point de départ pourrait être de regarder le plan d'exécution de la requête à la fois l'ancienne machine et la nouvelle machine. Il y aura certainement des différences d'optimisation avec les versions plus récentes de SQL Server. Le plan d'exécution peut vous montrer qu'un index est nécessaire, pour une raison quelconque, n'était pas aussi critique dans la version précédente.

+0

ok, merci ... comment puis-je faire cela? (Je n'ai pas fait cela avant, désolé!) – Alex

+0

Cliquez sur l'icône pour "Afficher le plan d'exécution réel" (survolez ech pour voir ce qu'ils sont) avant d'exécuter la requête dans SSMS. – tvanfosson

+0

je l'ai fait ... mais je ne sais pas trop quoi en faire - http://twitpic.com/x77ig/full (ce n'est pas le nouveau serveur) Il semble y avoir un coût élevé ... ? – Alex

1

Vous pouvez également envisager de mettre à jour les statistiques.

0

EDIT

Je ne sais pas ce que vous essayez de faire, mais si vous essayez d'obtenir des informations sur ce PO je pense que les changements ci-dessous vous aideront, vous avez

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_) 

Essayez ceci:

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_) 

en ce que la vitesse va, vous avez probablement besoin de mettre à jour certains index ... esp le champ Non_. De plus faire le changement suivant pour se débarrasser de la fuGetSalesOrderNumber() appelée sur chaque ligne:

;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 

Voir si cela fonctionne pour vous.

dédaigne les vieux trucs ci-dessous ...

Il est difficile pour moi de voir exactement ce que vous faites ici, mais il est rare OUTER sont nécessaires jointures - est-ce vraiment ce que vous voulez faire? Si c'est le cas, vous pouvez inverser l'ordre et avoir une jointure interne.Par exemple, vous dites:

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_ 

et vous pourriez dire

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_ 

En fonction de vos données, cela pourrait avoir un impact significatif sur votre temps d'exécution.

+0

je reçois une erreur sur la jointure lorsque je fais cela dans SSMS – Alex

1

Jointure interne gauche? Hmm, pas sûr si cela aiderait du tout ...

Si cette requête fonctionnait avant (données non performance) alors la requête ci-dessus gagnerait à transformer toutes vos jointures en INNER JOINs. Parce que vous êtes le fournisseur INNER JOINing sur une valeur de poHeader (qui est externe jointe), vous avez essentiellement fait une exigence de jointure interne sur poHeader aussi (sauf avec un succès de performance potentiel pour la jointure externe). Le fournisseur ne peut pas renvoyer de valeur à moins que poHeader ait une valeur et que le fournisseur soit joint à l'intérieur, la ligne entière sera ignorée s'il n'y a pas de valeur dans poHeader. Pareil avec salesHeader. La fonction utilisée dans la jointure nécessite une valeur dans poHeader (qui doit avoir une valeur selon la logique ci-dessus), donc cette jointure gagnerait à être transformée en INNER JOIN explicite au lieu d'être implicite. À part ça, je suis d'accord avec les affirmations sur les index (à l'exception de celle sur les jointures externes qui sont rarement nécessaires, c'est comme dire que vous n'avez pas besoin de tournevis si vous avez un marteau). L'indexation semble être l'explication la plus logique de la performance la plus faible. Plus précisément, vous devriez vérifier si votre table alias poForEmailing a un index sur ([traité], [copié]). Sans cet index, vous pouvez vous attendre à ce que votre temps de requête double au moins à mesure que la taille des données double car chaque enregistrement de cette table devra être testé par rapport à ces prédicats. En ce qui concerne votre question initiale, je n'ai rien remarqué dans SQL Server 2008 qui suggérerait un tel changement dans les performances, toutes choses égales par ailleurs.