La table T_PIN
a 300 000 broches et T_POLYGON
36 000 polygones. T_PIN
a cet indice:
CREATE SPATIAL INDEX [T_PIN_COORD] ON [dbo].[T_PIN]
(
[Coord]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
T_POLYGON
a:
CREATE SPATIAL INDEX [T_POLYGON_COORD] ON [dbo].[T_POLYGON]
(
[COORD]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
Une requête pour trouver l'intersection de T_PIN
et T_POLYGON
prend plus de 45 minutes à exécuter:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
Le résultat est de 4 438 318 lignes.
Comment puis-je accélérer cette requête?
Réponses:
Tout d'abord, vérifiez si un index spatial est utilisé en examinant le plan d'exécution des requêtes et voyez s'il existe un élément de recherche d'index clusterisé (spatial).
En supposant qu'il soit utilisé, vous pouvez essayer d'ajouter un filtre secondaire / simplifié basé sur une boîte englobante avec des polygones simplifiés à vérifier en premier. Des correspondances avec ces polygones simplifiés pourraient ensuite être exécutées à travers le filtre principal pour obtenir les résultats finaux.
1) Ajoutez une nouvelle colonne de géographie et de géométrie à la table [dbo]. [T_POLYGON]:
2) Créez les polygones de la boîte englobante (cela implique une conversion initiale en géométrie pour tirer parti de STEnvelope ()):
3) Créer un index spatial sur la colonne de géographie simplifiée
4) Obtenez les intersections avec cette colonne géographique simplifiée, puis filtrez à nouveau sur les types de données géographiques correspondants. En gros, quelque chose comme ça:
EDIT : vous pouvez remplacer (1) et (2) par cette colonne persistante calculée. crédit à Paul White pour la suggestion.
la source
De telles requêtes prennent souvent beaucoup de temps en raison de la complexité des polygones. J'ai vu des côtes complexes (par exemple) prendre du temps pour tester des points qui sont près de leurs limites, devant zoomer sur plusieurs niveaux pour savoir si un point est à l'intérieur ou à l'extérieur.
... pour que vous puissiez essayer
.Reduce()
les polygones, pour voir si cela aide.Et pour en savoir plus sur cette fonction, consultez http://msdn.microsoft.com/en-us/library/cc627410.aspx
la source
Selon les documents Microsoft, les index spatiaux seront utilisés avec les types géographiques sur les méthodes suivantes lorsqu'ils apparaissent au début d'un prédicat de comparaison avec une
WHERE
clause:STIntersects
STDistance
STEquals
Seules les méthodes des types de géométrie (liste restreinte) déclencheront l'utilisation de l'index spatial dans
JOIN ... ON
, donc changez votre code à utiliserWHERE geog1.STIntersects(geog2) = 1
et cela devrait améliorer la vitesse.Je recommande également de prendre des conseils dans la réponse de g2server et d'ajouter ce qui suit pour le filtrage et ajouter un index spatial dessus
vous pourriez alors avoir une requête comme la suivante (j'ai écrit ce post rapidement et je n'ai pas encore testé, c'est juste quelque chose à essayer car j'ai vu que votre requête et les réponses les plus élevées utilisent JOIN ON spatial op = 1 qui n'utilisera pas de indice spatial):
Pour info: ce qui précède ne fonctionne pas si
SimplePolysGeog
finissent par se chevaucher (comme dans une épingle peut être dans deux geogs simplifiés, il suffit de l'exécuter sur les personnes dans les circonscriptions dans un état et puisque les polys normaux partagent la frontière, les boîtes de délimitation se chevauchent), donc dans la plupart des utilisations cas, il générera une erreur indiquant que la sous-requête a renvoyé plusieurs résultats.De la vue d'ensemble des index spatiaux de MS Docs :
La requête suivante fonctionnera en cas de
SimplePolysGeogs
chevauchement:la source