{"id":7605,"date":"2018-10-25T07:30:26","date_gmt":"2018-10-25T10:30:26","guid":{"rendered":"http:\/\/www.fernandoquadro.com.br\/html\/?p=7605"},"modified":"2018-11-05T14:11:00","modified_gmt":"2018-11-05T17:11:00","slug":"juncao-espacial-5x-mais-rapida-com-postgis","status":"publish","type":"post","link":"https:\/\/www.fernandoquadro.com.br\/html\/2018\/10\/25\/juncao-espacial-5x-mais-rapida-com-postgis\/","title":{"rendered":"Jun\u00e7\u00e3o espacial 5x mais r\u00e1pida com PostGIS"},"content":{"rendered":"<p>Hoje veremos como \u00e9 poss\u00edvel aumentar a performance de sua consulta espacial com join, de uma maneira de certa forma &#8220;estranha&#8221;. Para este teste de desempenho com o PostGIS onde queremos saber quantos pontos est\u00e3o dentro de cada pol\u00edgono, temos: Uma cole\u00e7\u00e3o de pol\u00edgonos de tamanhos vari\u00e1veis \u200b\u200be uma cole\u00e7\u00e3o de pontos. <\/p>\n<p>Esse teste \u00e9 uma boa maneira de testar indexa\u00e7\u00e3o, c\u00e1lculos de pontos em pol\u00edgonos e sobrecarga geral.<\/p>\n<p><strong>1. Configura\u00e7\u00e3o<\/strong><\/p>\n<p>Primeiro baixe alguns pol\u00edgonos e alguns pontos:<\/p>\n<p>&#8211; <a href=\"https:\/\/www.naturalearthdata.com\/http\/\/www.naturalearthdata.com\/download\/10m\/cultural\/ne_10m_admin_0_countries.zip\" rel=\"noopener\" target=\"_blank\">Pa\u00edses<\/a><br \/>\n&#8211; <a href=\"https:\/\/www.naturalearthdata.com\/http\/\/www.naturalearthdata.com\/download\/10m\/cultural\/ne_10m_populated_places.zip\" rel=\"noopener\" target=\"_blank\">Lugares<\/a><\/p>\n<p>Carregue os shapefiles em seu banco de dados:<\/p>\n<pre>\r\nshp2pgsql -s 4326 -D -I ne_10m_admin_0_countries.shp countries | psql performance\r\nshp2pgsql -s 4326 -D -I ne_10m_populated_places.shp places | psql performance\r\n<\/pre>\n<p>Agora estamos prontos com 255 pa\u00edses e 7343 lugares.<\/p>\n<p><center> <img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/10\/ne-map.jpg\" alt=\"\" width=\"640\" height=\"480\" class=\"aligncenter size-full wp-image-7608\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/10\/ne-map.jpg 640w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/10\/ne-map-300x225.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/10\/ne-map-600x450.jpg 600w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/> <\/center><\/p>\n<p>Uma coisa a notar sobre os pa\u00edses \u00e9 que eles s\u00e3o objetos bastante grandes, com 149 deles tendo v\u00e9rtices suficientes para serem armazenados em tuplas <a href=\"https:\/\/www.postgresql.org\/docs\/11\/static\/storage-toast.html\" rel=\"noopener\" target=\"_blank\">TOAST<\/a>.<\/p>\n<pre>\r\nSELECT count(*) \r\n  FROM countries \r\n  WHERE ST_NPoints(geom) > (8192 \/ 16);\r\n<\/pre>\n<p><strong>2. Desempenho de baseline<\/strong><\/p>\n<p>Agora podemos executar o teste de desempenho de baseline.<\/p>\n<pre>\r\nSELECT count(*), c.name \r\n  FROM countries c \r\n  JOIN places p \r\n  ON ST_Intersects(c.geom, p.geom) \r\n  GROUP BY c.name;\r\n<\/pre>\n<p>Essa consulta levou <strong>25 segundos<\/strong>. Se voc\u00ea colocar o processo em um profiler enquanto o executa, descobrir\u00e1 que mais de 20 segundos s\u00e3o gastos na fun\u00e7\u00e3o pglz_decompress, e n\u00e3o fazendo algoritmos espaciais ou geometria computacional, apenas descomprimindo a geometria antes de entreg\u00e1-la ao processamento real.<\/p>\n<p>Por\u00e9m, existem maneiras inteligentes de evitar essa sobrecarga:<\/p>\n<ul>\n<li> Corre\u00e7\u00e3o do PostgreSQL para permitir a descompacta\u00e7\u00e3o parcial de geometrias.<\/li>\n<li> No formato de serializa\u00e7\u00e3o incluir uma chave hash exclusiva na frente das geometrias.<\/li>\n<\/ul>\n<p>Essas s\u00e3o maneiras legais de manter a compacta\u00e7\u00e3o para geometrias grandes e ser mais r\u00e1pido ao aliment\u00e1-las.<\/p>\n<p>No entanto, eles ignoram uma abordagem mais brutal e facilmente test\u00e1vel para evitar a descompress\u00e3o: apenas n\u00e3o comprimem em primeiro lugar.<\/p>\n<p><strong>3. Um truque estranho<\/strong><\/p>\n<p>O PostGIS usa a op\u00e7\u00e3o de armazenamento \u201cprincipal\u201d para seu tipo de geometria. A op\u00e7\u00e3o principal tenta manter as geometrias na tabela original at\u00e9 que elas fiquem muito grandes, depois as compacta e as move para TOAST.<\/p>\n<p>Existe outra op\u00e7\u00e3o \u201cexterna\u201d que mant\u00e9m as geometrias, e se elas ficarem muito grandes, s\u00e3o movidas para TOAST descomprimidas. O PostgreSQL permite que voc\u00ea altere o armazenamento em colunas em tempo de execu\u00e7\u00e3o, portanto n\u00e3o \u00e9 necess\u00e1rio hackear ou codificar para tentar isso.<\/p>\n<pre>\r\n-- Altere o tipo do storage\r\nALTER TABLE countries\r\n  ALTER COLUMN geom\r\n  SET STORAGE EXTERNAL;\r\n\r\n-- Force a reescrita da coluna\r\nUPDATE countries\r\n  SET geom = ST_SetSRID(geom, 4326);\r\n\r\n-- Execute novamente a query  \r\nSELECT count(*), c.name \r\n  FROM countries c \r\n  JOIN places p \r\n  ON ST_Intersects(c.geom, p.geom) \r\n  GROUP BY c.name;\r\n<\/pre>\n<p>A jun\u00e7\u00e3o espacial agora \u00e9 executada em menos de 4 segundos .<\/p>\n<p>Qual \u00e9 a penalidade?<\/p>\n<ul>\n<li> Com um armazenamento \u201cprincipal\u201d a tabela + toast + index \u00e9 de 6MB.<\/li>\n<li> Com um armazenamento \u201cexterno\u201d a tabela + toast + index \u00e9 de 9MB. <\/li>\n<\/ul>\n<p><strong>4. Conclus\u00e3o<\/strong><\/p>\n<p>Para uma penalidade de armazenamento de 50%, em uma tabela que possui objetos muito maiores do que a maioria das tabelas espaciais, alcan\u00e7amos uma melhoria de desempenho de 500%. Talvez n\u00e3o dev\u00eassemos aplicar compress\u00e3o \u00e0 nossa geometria?<\/p>\n<p>Usar o armazenamento \u201cprincipal\u201d foi principalmente uma chamada de julgamento quando decidimos, n\u00e3o foi aferido nem nada &#8211; \u00e9 poss\u00edvel que estiv\u00e9ssemos errados. Al\u00e9m disso, apenas objetos grandes s\u00e3o compactados; uma vez que a maioria das tabelas \u00e9 cheia de pequenos objetos (linhas curtas, pontos), mudar para &#8220;externo&#8221; por padr\u00e3o n\u00e3o teria qualquer efeito no tamanho do armazenamento.<\/p>\n<p><em>Este post foi traduzido e adaptado livremente do post originalmente escrito por Paul Ramsey, do blog CleverElephant.<\/em><\/p>\n<p>Fonte: <a href=\"http:\/\/blog.cleverelephant.ca\/2018\/09\/postgis-external-storage.html\" rel=\"noopener\" target=\"_blank\">Blog CleverElephant<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hoje veremos como \u00e9 poss\u00edvel aumentar a performance de sua consulta espacial com join, de uma maneira de certa forma &#8220;estranha&#8221;. Para este teste de desempenho com o PostGIS onde queremos saber quantos pontos est\u00e3o dentro de cada pol\u00edgono, temos:&#8230; <a class=\"more-link\" href=\"https:\/\/www.fernandoquadro.com.br\/html\/2018\/10\/25\/juncao-espacial-5x-mais-rapida-com-postgis\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":275,"featured_media":7607,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24],"tags":[212],"class_list":["post-7605","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gis","tag-postgis"],"_links":{"self":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/7605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/users\/275"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/comments?post=7605"}],"version-history":[{"count":15,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/7605\/revisions"}],"predecessor-version":[{"id":7642,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/7605\/revisions\/7642"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/media\/7607"}],"wp:attachment":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/media?parent=7605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/categories?post=7605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/tags?post=7605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}