2010-10-13 1 views
4

J'essaie d'optimiser une requête pour une base de données SQLServerCE exécutée sur un périphérique Windows Mobile. La requête est utilisée pour identifier les lignes à supprimer dans une table en fonction du fait qu'elles ne sont plus référencées à partir d'une table différente. La requête d'origine a utilisé un DISTINCT pour identifier les lignes correspondantes:Pourquoi la requête SQLServerCE effectue-t-elle une analyse de table et est-ce un problème?

SELECT TestGroupId, TestNameId, ServiceTypeId 
FROM ServiceTypeInspection 
WHERE ServiceTypeId NOT IN 
    (SELECT DISTINCT ServiceTypeId 
    FROM PurchaseOrder) 

Un rapide Google a suggéré d'utiliser EXISTE au lieu via:

SELECT TestGroupId, TestNameId, ServiceTypeId 
FROM ServiceTypeInspection AS STI 
WHERE NOT EXISTS 
    (SELECT PurchaseOrderId 
    FROM PurchaseOrder AS PO 
    WHERE (ServiceTypeId = STI.ServiceTypeId)) 

Mais je trouve aussi des suggestions sur SO et MSDN pour remplacer les deux options avec un LEFT JOIN qui semblait prometteur:

SELECT TestGroupId, TestNameId, STI.ServiceTypeId ServiceTypeId 
FROM ServiceTypeInspection STI 
LEFT JOIN PurchaseOrder PO ON STI.ServiceTypeId = PO.ServiceTypeId 
WHERE PO.ServiceTypeId IS NULL 

Lorsque j'exécute ces requêtes en tant que lot montrant le plan d'exécution, le coût par lot de la requête d'origine est 21%, la version NOT EXISTS est 11%, avec le LEFT JOIN responsable du solde de 68 % SSMS n'indique pas qu'il existe des index manquants, mais la requête NOT EXISTS a un coût de 25% lors d'une analyse de table. J'ai des index non-uniques sur ServiceTypeId dans les deux tables. Est-ce que je lis correctement la sortie du plan d'exécution que dans ce cas la version NOT EXISTS est la meilleure approche? La table scanne-t-elle un goulot d'étranglement potentiel ou est-ce normal pour un index non-unique?

Tableau définition est:

CREATE TABLE [PurchaseOrder](
[PurchaseOrderId] [uniqueidentifier] NOT NULL, 
[ServiceTypeId] [nvarchar](8) NOT NULL, 
CONSTRAINT [PK_PurchaseOrder] PRIMARY KEY 
(
    [PurchaseOrderId] 
) 
); 

CREATE TABLE [ServiceTypeInspection](
[TestGroupId] [int] NOT NULL, 
[TestNameId] [nvarchar](10) NOT NULL, 
[ServiceTypeId] [nvarchar](8) NOT NULL, 
CONSTRAINT [PK_ServiceTypeInspection] PRIMARY KEY 
(
    [TestGroupId],[TestNameId] 
) 
); 

CREATE INDEX IX_PurchaseOrder_ServiceTypeId ON [PurchaseOrder] (ServiceTypeId); 
CREATE INDEX IX_ServiceTypeInspection_ServiceTypeId ON [ServiceTypeInspection] (ServiceTypeId); 
+0

pouvez-vous publier les plans d'exécution respectifs s'il vous plaît (et tableau defn inc indexes) –

+0

J'ai posté les définitions de table (élidant les colonnes non pertinentes), mais les plans d'exécution consistent en une quantité substantielle de XML? –

+0

Utilisez-vous cette option pour une base de données complète ou une version de développement réduite? –

Répondre

1

Je pense que la taille de vos index NC sont relativement importantes par rapport à la taille de la table (grande clé primaire, qui je suppose est la valeur par défaut également index cluster, ce qui signifie que vous avez de grands index CN), l'optimiseur décide de numériser la table. En outre, si les indices IX_PurchaseOrder_ServiceTypeId et IX_ServiceTypeInspection_ServiceTypeId ont une sélectivité inférieure à environ 10%, l'optimiseur ne les utilisera probablement pas.

+0

Merci Mitch, comme d'habitude, il s'agit du contexte, n'est-ce pas? Est-ce que cela expliquerait pourquoi l'optimisation recommandée par MS pour l'utilisation d'un JOIN a un coût plus élevé que les autres options? –