Optimisation de la géométrie. Requête intersect

8

J'essaie de déplacer des routines de géotraitement simples des processus basés sur ESRI vers SQL Server. Je suppose que ce sera beaucoup plus efficace. Pour mon test initial, je travaille sur une routine d'intersection pour associer des données linéaires qui se chevauchent.

Dans ma table WCASING, j'ai 1610 enregistrements. J'essaie d'associer ces boîtiers avec leurs réseaux associés. J'ai ~ 277 000 Mains. J'ai ~ 1600 carters.

J'exécute la requête ci-dessous pour avoir une idée générale du temps qu'il faudra pour trouver des correspondances individuelles. Cette requête a renvoyé 5 intersections valides en 40 secondes.

SELECT Top 5 [WCASING].[OBJECTID] As CasingOBJECTID, 
    [WPUMPPRESSUREMAIN].[OBJECTID] AS MainObjectID, [WCASING].[Shape]
FROM [dbo].[WPUMPPRESSUREMAIN]
    JOIN [WCASING] 
        ON [WCASING].[Shape].STIntersects([WPUMPPRESSUREMAIN].[Shape]) = 1

Mes questions principales;

Ce processus sera-t-il plus rapide en fonction de l'ordre de recherche?

  • Trouver 'A' à l'intérieur de 'B' vs
  • Trouver «B» à l'intérieur de «A»
  • Le retour initial sur 5 enregistrements de ces ensembles de données est que cela n'a pas d'importance

Est-ce que ce processus sera plus rapide, si je tamponne d'abord pour limiter à un ensemble principal plus petit, puis recherche?

Puis-je utiliser SQL Server Tuning pour travailler avec des requêtes basées sur la géométrie?

SELECT WCASING.OBJECTID AS CasingOBJECTID,
    WPUMPPRESSUREMAIN.OBJECTID AS MainObjectID, WCASING.UFID AS UFID,
    WPUMPPRESSUREMAIN_IPS.UFID AS MainUFID, WCASING.SHAPE
INTO WCASING_INTDefsV6
FROM WCASING with (index([FDO_ShapeWC])) 
    INNER JOIN [WPUMPPRESSUREMAIN_IPS] ON 
        [WPUMPPRESSUREMAIN_IPS].Shape.STIntersects(WCASING.SHAPE) = 1

Cette nouvelle requête a amélioré les définitions.

  • Maintenant, les deux tables ont des index spatiaux
  • Auparavant, la table de tubage (plus petite) n'avait pas d'index spatial
    • Il contenait un index non clusterisé

La requête a également l'instruction with index.

La nouvelle requête a duré 37 minutes. L'ancienne requête prenait 44 minutes.

J'espérais de meilleurs résultats et je continuerai de tester.

Rick Monteiro
la source
1
amusant, n'est-ce pas!?
DPSSpatial
C'est génial. J'occupe un nouveau poste depuis un an, travaillant avec de très grands ensembles de données et la courbe d'apprentissage avec SQL Server a été la partie la plus agréable. Je suis toujours un noob à bien des égards, mais j'ai appris des trucs sympas.
Rick Monteiro
1
Nous utilisons les données spatiales et les fonctions de SQL Server pour notre analyse depuis près de 2 ans et nous ne reviendrons pas de sitôt !!!
DPSSpatial
Je m'attendrais à ce que forcer l'index sur une table plus grande (secteur) aurait de meilleures performances.
MickyT

Réponses:

7

Je suppose que vous utilisez des géométries, mais les méthodologies restent essentiellement les mêmes.

Lors du réglage des requêtes spatiales, voici les étapes que je prends

  1. C'est l'étape la plus importante . Vérifiez que les index conviennent à la table. Si vous avez SQL Server 2012+, je vous suggère d'utiliser la grille automatique. Cela vous donne une grille plus fine. Assurez-vous que les étendues couvrent les données et ne s'étendent pas trop loin. Si vous indexez des polygones ou des lignes, essayez de déterminer une valeur sensible de cellules par objet. La vue d'ensemble de l'indexation spatiale est assez bonne pour l'expliquer.

  2. Écrivez d'abord la requête dans sa forme la plus simple. Vérifiez le plan d'exécution estimé pour vous assurer que l'index spatial que vous attendez est utilisé. Exécutez la requête et obtenez les timings et les statistiques d'E / S. Un plan d'exécution réel serait également utile. Ce sera votre référence.

  3. Essayez des variantes de la requête, notamment en changeant l'ordre des géométries dans la comparaison de géométrie, etc. Collectez des statistiques pour chacune.

  4. Essayez de casser la requête en parties plus petites si possible (diviser pour mieux régner). Parfois, cela se traduit par une exécution globale plus rapide.

  5. Si tout le reste échoue et que vous ne pouvez pas demander à vos requêtes d'utiliser l'index spatial, utilisez l'index d'index. Ceci est un dernier recours et signifie potentiellement qu'il peut y avoir des problèmes avec l'indexation sur la table. Cela dit, l'optimiseur ne fait pas toujours les choses correctement.

Regardez les plans d'exécution et passez un peu de temps à essayer de les comprendre. Ils sont vraiment ton ami. Il existe également des outils qui les rendent plus faciles à interpréter. Celui que j'utilise est SQL Sentry .

En ce qui concerne la requête que vous avez publiée, je pense que ce sera la plus performante, mais voici une variante que vous voudrez peut-être essayer. L'opérateur TOP affectera également la façon dont le plan d'exécution est construit, ce qui signifie que vous n'obtiendrez probablement pas une bonne comparaison entre les différentes méthodes.

SELECT c.[OBJECTID] As CasingOBJECTID, 
    x.[OBJECTID] AS MainObjectID, 
    c.[Shape]
FROM [WCASING] c -- Smallest Table
    CROSS APPLY (
        -- This query is essentially done for each casing
        SELECT p.[OBJECTID]
        FROM [dbo].[WPUMPPRESSUREMAIN] p -- Largest table
        WHERE p.[Shape].STIntersects(c.[Shape]) = 1 -- should use the pressure main spatial index
        ) x
MickyT
la source
1

Ce que j'ai trouvé accélère le plus ces requêtes d'intersection, c'est forcer l'index spatial:

Dans une vue que je livre à BI qui intersecte ~ 280 000 points d'adresse avec ~ 300 polygones de limite, je force l'utilisation de l'index spatial du point d'adresse:

...

FROM [dpsdata].[Address_Master] as am with (index(SIndx_AddrMsterIC))
  left outer join [dpsdata].[SchoolBoundaries_All_Projected] as sbp
  on (am.shape.STIntersects(sbp.shape) =1)

(En supposant que les deux tables ont déjà des indices spatiaux construits ...)

Cela prend près de 1 min à exécuter, contre plusieurs minutes.

Dans votre cas, quelque chose comme ça devrait fonctionner:

SELECT Top 5 [WCASING].[OBJECTID] As CasingOBJECTID, 
    [WPUMPPRESSUREMAIN].[OBJECTID] AS MainObjectID, [WCASING].[Shape]
FROM [dbo].[WPUMPPRESSUREMAIN] with (index(PK__WPUMPPRE__E458E6E7F06C9A87)) 
    JOIN [WCASING] 
        ON [WCASING].[Shape].STIntersects([WPUMPPRESSUREMAIN].[Shape]) = 1
DPSSpatial
la source
J'ai essayé ça. Cela n'a pas fonctionné comme j'ai essayé de le mettre en œuvre. "SELECT Top 5 WCASING.OBJECTID AS CasingOBJECTID, WPUMPPRESSUREMAIN.OBJECTID_1 AS MainObjectID, WCASING.UFID, WCASING.SHAPE avec (index (PK__WPUMPPRE__E458E6E7F06C9A87)) INTO WCASPUSPRESSON "renvoie une erreur. "Msg 319, niveau 15, état 1, ligne 1 Syntaxe incorrecte près du mot clé" avec ". Si cette instruction est une expression de table courante, ..."
Rick Monteiro
Je n'ai jamais utilisé l'option «avec» auparavant. Est-ce spécifique à un champ ou à l'instruction From en général. Puis-je avoir deux instructions «with», une pour chaque table? Deuxième question, l'indice devrait-il être un indice spatial?
Rick Monteiro
1a) 'with' est utilisé dans ce cas dans l'instruction FROM et 1b) Je ne sais pas si cela fonctionnera si vous utilisez 2 'with' instructions ... 2) J'ai seulement essayé cela avec un index spatial
DPSSpatial
1
J'ai mis à jour ma réponse pour montrer comment vous pourriez utiliser votre index spatial dans la requête dans votre message d'origine ...
DPSSpatial
1
@RichardMonteiro désolé d'avoir oublié le 'avec' avant l'index spatial dans ma réponse en utilisant votre exemple ... J'ai mis à jour.
DPSSpatial