Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Otimizar busca de municipio do ponto por not-shared-cell #95

Open
ppKrauss opened this issue Oct 31, 2024 · 1 comment
Open

Otimizar busca de municipio do ponto por not-shared-cell #95

ppKrauss opened this issue Oct 31, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@ppKrauss
Copy link
Contributor

A vantagem da busca por células interiores (is_inner) é que a busca pode se restringir à BBOX (operador &&), sem conferir a interseção com o polígono. O número de células marcadas com is_inner, todavia, na maior parte dos países, não passa de 30%.

... Esquecemos que o ponto para "estar no município X" não precisa estar "dentro do polígono do município X", basta estar na sua cobertura. Usando essa propriedade podemos trocar o flag por is_not_shared (ou "is_unique"). No Brasil isso significa incluir todas as células de cobertura de litoral e fronteiras, acrescentando mais uns 20% de células municipais.

Conclusão: com a simples troca de flag chegamos nos 50% de comparações por BBOX, e excluimos elas das comparações por interseção.

Importante: a indexação GIST precisaria ser pela operação da busca, is_not_shared OR ST_Intersects(?), mas
  WHERE pt_geom && cell_geom AND (is_not_shared OR ST_Intersects(pt_geom,cell_geom)).

... testar com dois indices, um com outro sem o flag:


Toda célula interior é is_not_shared, mas precisamos expandir. Construção do flag is_not_shared para as células de cobertura municipal (não overlay).

UPDATE t SET is_not_shared=true
WHERE gid IN (SELECT gid FROM cobertura_municipal GROUP BY 1 HAVING COUNT(*)=1)

Problema: isso vale para células de mesmo nível, falta remover as grandes que cobrem as pequenas.

@ppKrauss ppKrauss added the enhancement New feature or request label Oct 31, 2024
@ppKrauss
Copy link
Contributor Author

ppKrauss commented Nov 4, 2024

Chegamos a um percentual pequeno de células não-compartilhadas... Aparentemente não há ganho, conforme explain (buffers, analyze) , quando indexamos apenas o is_contained. Mudando a estratégia... Suponha o seguinte cenário de teste:

explain (buffers, analyze) 
with p AS (SELECT ST_transform(ST_Point(-45.697189,-22.686177,4326),952019) AS pt_geom, 1234 as cindex)
select isolabel_ext, cindex, is_contained  
from p, osmc.coverage t 
where not(t.is_country) AND NOT(t.is_overlay)
  AND   t.geom && p.pt_geom AND (t.is_contained OR ST_Intersects(t.geom,p.pt_geom));

Trocando operador BBOX por comparação de ID

A operação t.geom && p.pt_geom foi otimizada, é rápida, mas será que conferir um ID (do tipo hInt64) não seria ainda mais rápido?

Toda vez que buscamos um ponto, esse ponto já pode vir pronto com seu ID na origem, ou seja, o requisitante já pode fazer isso. Temos duas representações para o mesmo ponto de input, ID e geometria. Idem na tabela de coberturas (gid e geom).

Então podemos acrescentar mais uma coluna na tabela de coberturas, o gid_max para representar o limite superior da árvore à qual a célula pertence. UPDATE cover SET gid_max=hint_to_max(gid). Podemos então indexar a tabela:

CREATE UNIQUE INDEX cover_gid_idx1 ON cover (gid)
  WHERE NOT(is_country) AND NOT(is_overlay) AND is_not_shared
;
CREATE INDEX cover_gid_idx2 ON cover (gid)
  WHERE NOT(is_country) AND NOT(is_overlay) AND NOT(is_not_shared)
;

CREATE UNIQUE INDEX cover_gidmax_idx1 ON cover (gid_max)
  WHERE NOT(is_country) AND NOT(is_overlay) AND is_not_shared
;  -- provamos que se gid é unico então gid_max é unico.
CREATE INDEX cover_gidmax_idx2 ON cover (gid_max)
  WHERE NOT(is_country) AND NOT(is_overlay) AND NOT(is_not_shared)
; 

CREATE INDEX cover_geom_idx1 ON cover USING GIST (geom)
  WHERE NOT(is_not_shared)
;

A consulta a analisar seria

...
WHERE NOT(t.is_country) AND NOT(t.is_overlay)
  AND  p.pt_gid BETWEEN t.gid AND t.gid_max AND (t.is_not_shared OR ST_Intersects(t.geom,p.pt_geom));

Varbit suficiente para o teste de performance

Devido à indexação btree, a performance varbit não será pior do que bigint. Basta indexar.

Duas opções, trocar ou manter gid e incluir gid_vbit na tabela.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants