5.1. Petites tables comportant de vastes objets géométriques



 Table des matières

5.1.1. Description du problème
5.1.2. Solutions de contournement

5.1.1. Description du problème

Les versions actuelles de PostgreSQL (dont 8.0) souffrent d'un défaut de l'optimiseur de requêtes en ce qui concerne les tables TOAST. Les tables TOAST sont une sorte
d'"espace supplémentaire" servant à stocker de "grandes" valeurs (grandes au sens de la taille des données) qui ne peuvent loger dans des pages de données normales (comme les longs textes, les images, ou les géométries complexes comportant un grand nombre d'arcs), voir http://www.postgresql.org/docs/8.0/static/storage-toast.html pour plus d'information).
Le problème apparait si vous possédez une table avec des géométries de taille importantes, mais avec peu de tuples (par exemple une table contenant les frontières des pays européens en haute résolution). La table elle-même est relativement petite, mais elle utilise énormément d'espace TOAST. Dans notre exemple, la table compte environ 80 lignes (ou tuples), et n'utilise que 3 pages de données, mais la table TOAST utilise 8225 pages.
A présent, essayez de lancer une requête en utilisant l'opérateur géométrique && pour rechercher une boite englobante qui ne comprend que quelques-uns de ces tuples.
L'optimiseur de requête constate que votre table ne compte que 3 pages et 80 lignes. Il estime par conséquent qu'un scan séquentiel sur une si petite table est beaucoup plus rapide que d'utiliser un index. Et il choisir d'ignorer l'index GIST. D'ordinaire, son estimation est juste mais dans notre cas, l'opérateur && doit aller récupérer chaque objet géométrique sur le disque pour comparer les boites englobantes, et il parcoure par la même occasion toutes les pages TOAST.
Pour vérifier si vous pâtissez de ce bogue, utilisez la commande "EXPLAIN ANALYZE" de postgresql. Pour plus d'informations et des détails techniques, vous pouvez lire ce sujet sur la liste de discussion des performances de postgres : http://archives.postgresql.org/pgsql-performance/2005-02/msg00030.php

haut de la page | table des matières

5.1.2. Solutions de contournement

Les développeurs de PostgreSQL essayent de résoudre ce problème en faisant en sorte que l'estimateur de la requête prenne en considération l'espace TOAST. Pour le moment, voici deux solutions de contournement :

La première est de forcer le préparateur de requête à utiliser l'index. Envoyez "SET enable_seqscan TO off;" au serveur avant de lancer la requête. Cela force le préparateur de requête à éviter les scans séquentiels intempestifs lorsque c'est possible. Il utilise alors l'index GIST comme d'habitude. Cependant, ce drapeau doit être fixé à chaque connexion, et il conduit le préparateur de requête à faire des erreurs d'estimation dans d'autres cas de figure, il faut donc le remettre à "SET enable_seqscan TO on;" après la requête.

La seconde solution est de rendre le scan séquentiel aussi rapide que le préparateur de requête le pense. Cela peut se faire en créant un champ additionnel qui met la boîte englobante en cache, et de se servir de ce nouveau champ pour opérer les comparaisons. Dans notre exemple, les commandes sont :

SELECT addGeometryColumn('myschema','mytable','bbox','4326','GEOMETRY','2');

UPDATE mytable set bbox = Envelope(Force_2d(the_geom));

Maintenant, changez votre requête en utilisant l'opérateur && sur la boîte englobante à la place de geom_column, comme suit:

SELECT geom_column FROM mytable WHERE bbox && SetSrid('BOX3D(0 0,1 1)'::box3d,4326);

Bien entendu, si vous changez ou ajoutez des lignes à mytable, vous devrez veiller à ce que la boîte englobante reste à jour. La façon la plus transparente de faire cela est par une moulinette automatique, mais vous pouvez aussi modifier votre application pour que le champ de la boîte englobante reste à jour de façon permanente ou lancer la requête UPDATE après chaque modification.

haut de la page | table des matières