Pourquoi la requête SQLServerCE effectue-t-elle une parsing de table et est-ce un problème?

J'essaie d'optimiser une requête pour une database 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:

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

Un google rapide a suggéré d'utiliser EXISTS à la place via:

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

Mais j'ai également trouvé des suggestions sur SO et MSDN pour replace les deux options par 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 sous la forme d'un lot affichant le plan d'exécution, le coût par lot de la requête d'origine est de 21%, la version NOT EXISTS est de 11%, le LEFT JOIN étant responsable du solde de 68%. SSMS n'indique pas qu'il existe des index manquants mais la requête NOT EXISTS la plus rapide a un coût de 25% dans un scan 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?

La définition du tableau 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); 

Je suppose que la taille de vos index CN est relativement grande par rapport à la taille de la table (grande key primaire, que je suppose être l'index cluster par défaut, ce qui signifie que vous avez de grands index CN), donc l'optimiseur décide de balayage.

En outre, si les index IX_PurchaseOrder_ServiceTypeId et IX_ServiceTypeInspection_ServiceTypeId ont une IX_ServiceTypeInspection_ServiceTypeId inférieure à environ 10%, l'optimiseur ne les utilisera probablement pas.