2010-10-06 14 views
0

J'ai une énorme table partitionnée stockée dans une table PostgreSQL. Chaque table enfant a un index et une contrainte de vérification sur son identifiant, par ex. (Deatils non pertinents pour plus de clarté):Partitionnement de table PostgreSQL +: inefficace max() et min()

Master table: points 
    Column  |   Type    |  Modifiers   
---------------+-----------------------------+------------------------ 
id   | bigint      | 
creation_time | timestamp without time zone | 
the_geom  | geometry     | 


Sub-table points_01 
    Column  |   Type    |  Modifiers   
---------------+-----------------------------+------------------------- 
    id   | bigint      | 
creation_time | timestamp without time zone | 
the_geom  | geometry     | 

Indexes: 
    "points_01_pkey" PRIMARY KEY, btree (id) 
    "points_01_creation_time_idx" btree (creation_time) 
    "points_01_the_geom_idx" gist (the_geom) CLUSTER 
Check constraints: 
    "enforce_srid_the_geom" CHECK (srid(the_geom) = 4326) 
    "id_gps_points_2010_08_22__14_47_04_check" 
       CHECK (id >= 1000000::bigint AND id <= 2000000::bigint) 

Maintenant,

SELECT max(id) FROM points_01 

est instantanée, mais:

SELECT max(id) FROM points 

qui est une table principale pour points_01 .. points_60 et devrait prendre très peu de temps à l'aide vérifier les contraintes, prend plus d'une heure car le planificateur de requêtes n'utilise pas les contraintes de vérification. Selon le wiki PostgreSQL (dernière section de this page), il s'agit d'un problème connu qui sera corrigé dans les prochaines versions.

Y a-t-il un bon hack qui fera en sorte que le planificateur de requêtes utilise les contraintes de vérification et les index des sous-tables pour les requêtes max() et min()?

Merci,

Adam

+0

Pouvez-vous montrer votre plan d'exécution? –

Répondre

1

Réponse courte: Non. À ce stade, il est impossible de faire comprendre au planificateur Postgres que certaines fonctions d'agrégat peuvent d'abord vérifier les contraintes sur les partitions enfants. C'est assez facile à prouver pour un cas spécifique de min et max, mais pour les agrégats en général, c'est un cas difficile.

Vous pouvez toujours écrire comme une union de plusieurs partitions quand il vient d'être fait ...

1

Je ne sais pas si cela va fonctionner, mais vous pouvez essayer ceci:

Pour cette session, vous pouvez désactiver toutes les stratégies d'accès, mais celles indexées:

db=> set enable_seqscan = off; 
db=> set enable_tidscan = off; 
db=> -- your query goes here 

De cette façon, seuls bitmapscan et indexscan seraient activés. PostgreSQL n'aura d'autre choix que d'utiliser des index pour accéder aux données de la table.

Après l'exécution de votre requête, n'oubliez pas réactivez seqscan et tidscan en faisant:

db=> set enable_seqscan = on; 
db=> set enable_tidscan = on; 

Dans le cas contraire, ces stratégies d'accès seront désactivées pour la session de ce moment-là.

+0

Ces paramètres sont-ils spécifiques à la session ou globaux? –

+1

Vous pouvez les rendre globaux en changeant "postgresql.conf". Mais je vous décourage fortement de le faire. Si vous utilisez ** set **, ils seront spécifiques à la session. Comme je le dis dans la réponse, désactiver seqscan et tidscan ** SEULEMENT POUR CETTE DEMANDE ** et les réactiver immédiatement. –

0

Je ne sais pas beaucoup de Postgres mais vous pouvez pourrais essayer cette requête (Ma syntaxe de requête peut être pas correct en raison du manque d'expérience avec les requêtes postgres):

SELECT id FROM points a WHERE id > ALL (SELECT id FROM x WHERE x.id != a.id) 

Je suis curieux de savoir si cela fonctionne.