J'ai des données OpenStreetMap pour les Pays-Bas chargées dans une base de données PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) en utilisant le schéma d'osmose . Cela signifie que toutes les balises sont stockées dans un champ hstore . En plus de l'index GIST que l'osmose crée sur le champ géométrique, j'ai créé un index GIST supplémentaire sur le champ tags.
En essayant d'interroger en utilisant à la fois une contrainte spatiale et une contrainte sur le champ des balises, je trouve que c'est plus lent que je ne le souhaiterais. Une requête comme celle-ci:
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n
INNER JOIN users AS u ON n.user_id = u.id
WHERE tags->'man_made'='surveillance'
AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));
prend 22 secondes pour renvoyer 78 enregistrements.
Il y a environ 53 millions d'enregistrements dans ce tableau.
Existe-t-il un moyen d'accélérer considérablement cette opération? J'ai entendu dire que hstore est implémenté beaucoup mieux dans PostgreSQL 9, la mise à niveau serait-elle utile?
Réponses:
Une méthode serait de rechercher les balises qui vous intéressent et de placer ces enregistrements dans une nouvelle table. Vous n'aurez alors qu'à interroger la nouvelle table au lieu des 53 millions d'enregistrements. Si vous essayez de maintenir votre base de données à jour, vous pouvez exécuter cette requête chaque fois que vous obtenez de nouvelles données d'OSM.
la source
Vous pouvez essayer de créer un index pour votre colonne hstore,
puis utilisez l'
?
opérateur pour limiter la requête aux seules lignes suivantes:la source
?
opérateur a pris 48 secondes contre 88 secondes pour ma requête (je ne sais pas comment j'ai obtenu 72 secondes hier, peut-être que la machine faisait quelque chose de compliqué cette fois pendant que j'effectuais les requêtes). Donc, ce n'est toujours pas la performance que je recherche, mais j'ai acquis une meilleure compréhension du fonctionnement des index GIST sur les colonnes hstore. Je devrai toujours aller avec l'autre solution de création d'une vue matérialisée pour obtenir les performances que je souhaite.Les fonctions st_within et _st_within ne sont pas connues pour leur vitesse. L'opérateur && pourrait aider car il vérifiera la bbox au lieu de la géométrie
Vous pouvez essayer ce qui suit:
Pour plus de conseils sur les performances, consultez: http://postgis.refractions.net/docs/ch06.html
la source
Le problème avec votre requête est la
tags->'man_made'='surveillance'
clause. Cela oblige Postgres à développer les balises hstore et ne lui permet pas d'utiliser l'index. Si vous réécrivez ceci en utilisant@>
(contient), cela permettra l'utilisation de l'index.Parce que vous interrogez un rectangle, vous pouvez utiliser à la
&&
place de ST_Within. Cela aura un petit gain, car le ST_Within n'est pas si compliqué à évaluer, et ST_Within effectue implicitement une&&
vérification.Une augmentation supplémentaire de la vitesse consisterait à utiliser un index GIN sur les balises au lieu d'un index GIST. La construction des index GIN prend plus de temps mais est plus rapide.
La requête entière serait
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n INNER JOIN users AS u ON n.user_id = u.id WHERE tags @> hstore('man_made', 'surveillance') AND geom && ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326);
Si vous savez que vous allez souvent interroger une balise particulière, vous pouvez créer un index partiel avec
CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);
.Cela permettra à la condition WHERE
tags->'man_made'='surveillance'
d'utiliser l'index. Malheureusement, cet index ne peut pas aider les@>
requêtes et les index GIN ou GIST ne peuvent pas aider lestags->'foo'
requêtes, vous devez donc faire correspondre les requêtes aux index que vous avez.la source
tags @>hstore()
considérablement amélioré ma requête, merci.essayez plutôt ceci:
SELECT n.geom, n.tags, n.tstamp, u.name FROM nœuds AS n INNER JOIN utilisateurs AS u ON n.user_id = u.id WHERE tags @> 'man_made => surveillance' :: hstore AND ST_Within (geom , ST_GeomFromText ('POLYGON ((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))', 4326));
la source