A tabela T_PIN
possui 300.000 pinos e T_POLYGON
36.000 polígonos. T_PIN
tem este índice:
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
tem:
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];
Uma consulta para encontrar a interseção T_PIN
e T_POLYGON
leva mais de 45 minutos para executar:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
O resultado é 4.438.318 linhas.
Como posso acelerar esta consulta?
Respostas:
Primeiramente, verifique se um índice espacial está sendo usado, observando o plano de execução da consulta e veja se há um item de Procura de Índice em Cluster (Espacial).
Supondo que ele esteja sendo usado, você pode tentar adicionar um filtro secundário / simplificado com base em uma caixa delimitadora com polígonos simplificados para verificar primeiro. As correspondências com esses polígonos simplificados poderiam ser executadas no filtro primário para obter os resultados finais.
1) Adicione uma nova coluna de geografia e geometria à tabela [dbo]. [T_POLYGON]:
2) Crie os polígonos da caixa delimitadora (isso envolve uma conversão inicial em geometria para aproveitar o STEnvelope ()):
3) Crie um índice espacial na coluna de geografia simplificada
4) Obtenha as interseções nessa coluna de geografia simplificada e filtre novamente os tipos de dados geográficos correspondentes. Aproximadamente, algo como isto:
EDIT : você pode substituir (1) e (2) por esta coluna persistente calculada. agradecemos a Paul White pela sugestão.
fonte
Consultas como essa geralmente levam muito tempo devido à complexidade dos polígonos. Eu já vi linhas costeiras complexas (por exemplo) levarem séculos para testar pontos que estão próximos de seus limites, tendo que ampliar muitos níveis para descobrir se um ponto está dentro ou fora.
... para tentar
.Reduce()
os polígonos, para ver se isso ajuda.E para saber mais sobre essa função, consulte http://msdn.microsoft.com/en-us/library/cc627410.aspx
fonte
De acordo com os documentos da Microsoft, os índices espaciais serão usados com os tipos de região geográfica nos métodos a seguir quando aparecerem no início de um predicado de comparação com uma
WHERE
cláusula:STIntersects
STDistance
STEquals
Somente os métodos dos tipos de geometria (lista restrita) acionarão o uso do índice espacial
JOIN ... ON
, portanto, mude seu código para usarWHERE geog1.STIntersects(geog2) = 1
e isso deve melhorar a velocidade.Também recomendo seguir o conselho da resposta do g2server e adicionar o seguinte para filtrar e adicionar índice espacial nele
você poderia então ter uma consulta como a seguinte (escrevi esta postagem rapidamente e ainda não a testei, isso é apenas algo para tentar, porque eu vi que sua consulta e as respostas mais altas postadas usam JOIN ON spatial op = 1, que não usará um índice espacial):
Para sua informação: O exemplo acima não funciona se
SimplePolysGeog
acabar sobreposto (como em um alfinete pode estar em dois geogs simplificados, apenas o executei em pessoas em distritos de um estado e, como os polys normais compartilham o limite, as caixas delimitadoras se sobrepõem), portanto, na maior parte do uso casos, lançará um erro que a subconsulta retornou mais de um resultado.Da visão geral dos índices espaciais do MS Docs :
A consulta a seguir funcionará se
SimplePolysGeogs
sobrepor:fonte