Otimizando a consulta Geometry.STIntersect

8

Estou tentando mover rotinas simples de geoprocessamento dos processos baseados em ESRI para o SQL Server. Minha suposição é que será muito mais eficiente. Para o meu teste inicial, estou trabalhando em uma rotina de interseção para associar dados lineares sobrepostos.

Na minha tabela WCASING, tenho 1610 registros. Estou tentando associar essas tripas às suas redes associadas. Eu tenho ~ 277.000 Mains. Eu tenho ~ 1.600 tripas.

Estou executando a consulta abaixo para ter uma noção geral de quanto tempo levará para encontrar correspondências individuais. Esta consulta retornou 5 interseções válidas em 40 segundos.

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

Minhas perguntas primárias;

Esse processo será mais rápido, dependendo da ordem de pesquisa?

  • Encontrar 'A' dentro de 'B' vs
  • Encontrar 'B' dentro de 'A'
  • O retorno inicial de 5 registros desses conjuntos de dados é que isso não importa

Esse processo será mais rápido se eu primeiro fizer um buffer para limitar a um conjunto principal menor e depois pesquisar?

Posso usar o SQL Server Tuning para trabalhar com consultas baseadas em geometria?

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

Esta nova consulta melhorou as definições.

  • Agora ambas as tabelas têm índices espaciais
  • Anteriormente, a tabela de revestimento (menor) não tinha um índice espacial
    • Continha um índice não clusterizado

A consulta também possui a instrução with index.

A nova consulta levou 37 minutos. A consulta antiga levou 44 minutos.

Eu esperava melhores resultados e continuarei testando.

Rick Monteiro
fonte
1
divertido, não é?
DPSSpatial #
É incrivel. Estou em uma nova posição há um ano, trabalhando com conjuntos de dados muito grandes e a curva de aprendizado com o SQL Server tem sido a parte mais agradável. Ainda sou um noob de várias maneiras, mas aprendi algumas coisas legais.
Rick Monteiro
1
Estamos usando dados e funções espaciais do SQL Server para nossa análise há quase 2 anos e não voltaremos tão cedo !!!
DPSSpatial
Eu esperava que forçar o índice na tabela maior (rede elétrica) tivesse um desempenho melhor.
MickyT 5/05

Respostas:

7

Suponho que você esteja usando geometrias, mas as metodologias permanecem basicamente as mesmas.

Ao ajustar consultas espaciais, estas são as etapas que eu tomo

  1. Este é o passo mais importante . Verifique se os índices são adequados para a tabela. Se você possui o SQL Server 2012 ou superior, sugiro que você use a grade automática. Isso fornece uma grade mais fina. Verifique se as extensões cobrem os dados e não se estendem para muito longe deles. Se indexar polígonos ou linhas, tente determinar um valor sensível de Células por Objeto. A visão geral da indexação espacial é bastante boa para explicá-la.

  2. Escreva a consulta em sua forma mais simples primeiro. Verifique o Plano de execução estimado para garantir que o índice espacial que você espera esteja sendo usado. Execute a consulta e obtenha os horários e as estatísticas de E / S. Um plano de execução real também seria útil. Essa será sua linha de base.

  3. Tente variações da consulta, incluindo a troca da ordem das geometrias na comparação de geometrias, etc. Reúna estatísticas para cada uma.

  4. Tente quebrar a consulta em partes menores, se possível (dividir e conquistar). Às vezes, isso resulta em uma execução mais rápida geral.

  5. Se tudo mais falhar e você não conseguir que suas consultas usem o índice espacial, use a dica de índice. Este é o último recurso e, potencialmente, significa que pode haver problemas com a indexação na tabela. Dito isto, o otimizador nem sempre acerta.

Veja os planos de execução e gaste um pouco de tempo tentando entendê-los. Eles são realmente seus amigos. Também existem ferramentas que os tornam mais fáceis de interpretar. O que eu uso é o SQL Sentry .

Quanto à consulta que você postou, acho que será o melhor desempenho, mas aqui está uma variação que você pode tentar. Além disso, o operador TOP afetará a maneira como o plano de execução é construído, portanto, isso significa que você provavelmente não terá uma boa comparação entre diferentes métodos.

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
fonte
1

O que eu descobri acelera mais essas consultas de interseção está forçando o índice espacial:

Em uma exibição que entrego ao BI, que cruza ~ 280.000 pontos de endereço com ~ 300 polígonos de limite, forço o uso do índice espacial do ponto de endereço:

...

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)

(Supondo que ambas as tabelas tenham índices espaciais já construídos, é claro ...)

Isso leva cerca de 1 minuto para ser executado, depois de alguns minutos.

No seu caso, algo como isto deve funcionar:

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
fonte
Eu tentei isso. Não funcionou da maneira que tentei implementá-lo. "SELECT TOP 5 WCASING.OBJECTID AS CasingOBJECTID, WPUMPPRESSUREMAIN.OBJECTID_1 AS MainObjectID, WCASING.UFID, WCASING.SHAPE com (índice (PK__WPUMPPRE__E458E6E7F06C9A87)) EM WCASING_INTDefs_V2 DE WCASING INNER JOIN WPUMPPRESSUREMAIN NO WPUMPPRESSUREMAIN.Shape.STIntersects (WCASING.SHAPE) = 1 "retorna um erro. "Msg 319, Nível 15, Estado 1, Linha 1 Sintaxe incorreta perto da palavra-chave 'com'. Se esta declaração for uma expressão de tabela comum, ..."
Rick Monteiro
Eu não usei a opção 'with' antes. Isso é específico para um campo ou para a declaração From em geral. Posso ter duas instruções 'with' uma para cada tabela? Segunda pergunta, o índice deve ser um índice espacial?
Rick Monteiro
1a) 'with' é usado neste caso na instrução FROM e 1b) Não sei se funcionará se você usar 2 'with' ... 2) Eu só tentei isso com um índice espacial
DPSSpatial
1
Eu atualizei a minha resposta para mostrar como você pode usar o índice espacial na consulta em seu post original ...
DPSSpatial
1
@RichardMonteiro desculpe, esqueci o 'with' antes do índice espacial na minha resposta usando o seu exemplo ... Eu atualizei.
DPSSpatial 5/05