J'ai une table avec 50K lignes. Il s'agit en fait d'une table PostGIS.
La requête comprend 4 parties (1 obligatoire) (3 facultatives)
- boîte d'intersection (un rectangle de géographie) avec 4 lat, longue (j'utilise st_intersects) [Obligatoire]
- Plage de dates (min, max) sur un champ de date
- Type de fichier (un ensemble de jusqu'à 8 valeurs de texte) utilisant actuellement IN (.....) mais je peux en faire une table temporaire si nécessaire. Je vois que beaucoup de gens n'aiment pas IN.
- Pays (une valeur de texte).
J'attends environ 100 à 4 000 lignes renvoyées
Si je crée un index composé sur la table, quelle colonne dois-je utiliser en premier. Le grain fin est probablement l'emplacement (les données sont réparties dans le monde entier). Je l'ai actuellement comme index GIST.
Les autres indices seraient BTREE.
Mon intuition dit d'utiliser du grain fin, et bien sûr durer. Par exemple, il n'y a qu'environ 12 types de fichiers, ce qui constituerait de très gros compartiments pour l'index.
Que disent les gourous PostgreSQL et PostGIS (qui connaissent les composants internes du système)?
MISE À JOUR:
Permettez-moi d'affiner cette question.
- Je ne veux pas que quiconque doive faire le travail que je devrais faire. Je respecte trop votre temps. Je vais donc passer à l'analyse d'expliquer plus tard.
- Tout ce que je cherchais, c'était des pointeurs, des conseils et des directives.
- J'ai lu cette excellente petite publication: https://devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintaining-indexes sur les index
- Ce que je fais normalement, c'est créer 4 index distincts (boîte géographique, nom de pays, type_fichier et date), mais ce que je veux voir ce que ferait une requête composite.
Dites-moi si l'une de ces hypothèses est fausse. (Je suis assez nouveau dans l'idée des indices composés)
- L'ordre est important. Choisissez comme premier index celui qui coupera le plus les lignes (dans mon cas, l'emplacement (géographie) qui est un simple polygone ou multi-polygone ferait le mieux).
- Parfois, les requêtes ignorent les index. Mais si je crée une requête composée avec clé (# 1, # 2, # 3, # 4), même si l'utilisateur crée quelque chose qui demande # 1, # 3, le planificateur utilisera toujours la seule requête composite, car il commande est maintenu.
- Normalement, je créerais trois requêtes BTREE et une GIST (pour le type geography). PostGIS ne prend pas en charge la création d'un composé à partir de plusieurs types d'index. Je vais donc devoir utiliser GIST l'indice composé. Mais cela ne devrait pas blesser les choses.
- Si je crée des index composés ou à valeur unique supplémentaires, le planificateur est assez intelligent pour choisir le plus intelligent .....
- Le nom du pays peut avoir environ 250 valeurs différentes et est évidemment fortement lié à l'emplacement (géobox), mais si le prochain meilleur index pour réduire la taille de la ligne est file_type, je devrais l'utiliser ensuite. Je ne m'attends pas à ce que les utilisateurs utilisent souvent le pays ou la date dans leurs ensembles de requêtes.
- Je n'ai PAS à vous soucier de créer un index composé de 4 clés augmentera considérablement la taille des données d'index. Autrement dit, si un indice à une clé représente 90% de l'augmentation des performances, cela ne fait pas de mal d'ajouter 3 éléments supplémentaires pour le rendre composé. Inversement, je devrais vraiment créer les deux index. Un index géographique unique, ainsi qu'un index composé, et laissez le planificateur déterminer ce qui est le mieux, et il prendra en compte la taille de la table d'index.
Encore une fois, je ne demande à personne de concevoir ma solution, je ne me moque pas du travail des autres. Mais j'ai besoin de choses que la documentation PostGreSQL ne me dit pas sur l'implémentation
[La raison pour laquelle je n'ai pas encore de résultat EXPLAIN à montrer, c'est que je dois créer ce tableau de 25 Ko à partir d'un tableau de 24 Mo. Cela prend plus de temps que je ne le pensais. Je regroupe les choses en 1 000 groupes d'articles et laisse l'utilisateur interroger la table de lignes de 25 Ko. Mais ma prochaine question, impliquera d'utiliser les résultats de cette requête pour accéder à la table de lignes MASTER 25M et retirer les choses, et c'est là que les performances de l'indice composé vont vraiment HIT].
exemple de requête ci-dessous:
SELECT
public.product_list_meta_mv.cntry_name AS country,
public.product_list_meta_mv.product_producer AS producer,
public.product_list_meta_mv.product_name AS prod_name,
public.product_list_meta_mv.product_type AS ptype,
public.product_list_meta_mv.product_size AS size,
ST_AsGeoJSON(public.product_list_meta_mv.the_geom, 10, 2) AS outline
FROM
public.product_list_meta_mv
WHERE
public.product_list_meta_mv.cntry_name = 'Poland'
AND
ST_Intersects(public.product_list_meta_mv.the_geom,
st_geogfromtext('SRID=4326;POLYGON((21.23107910156250 51.41601562500000,
18.64379882812500 51.41601562500000,
18.64379882812500 48.69415283203130,
21.23107910156250 48.69415283203130,
21.23107910156250 51.41601562500000))'))
AND (date >= '1/2/1900 5:00:00 AM'
AND date <= '2/26/2014 10:26:44 PM')
AND (public.product_list_meta_mv.product_type in
('CIB10','DTED0','DTED1','DTED2','CIB01','CIB05')) ;
EXPLIQUEZ LES RÉSULTATS DE L'ANALYSE (je n'ai pas mis d'index composés, et à partir de la vitesse que je vois, je ne sais pas si j'en ai besoin).
"Bitmap Heap Scan on catalog_full cat (cost=4.33..37.49 rows=1 width=7428) (actual time=1.147..38.051 rows=35 loops=1)"
" Recheck Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
" Filter: (((type)::text = ANY ('{CADRG,CIB10,DTED1,DTED2}'::text[])) AND (_st_distance('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography, outline, 0::double precision, false) < 1e-005::double precision))"
" Rows Removed by Filter: 61"
" -> Bitmap Index Scan on catalog_full_outline_idx (cost=0.00..4.33 rows=8 width=0) (actual time=0.401..0.401 rows=96 loops=1)"
" Index Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"Total runtime: 38.109 ms"
EXPLAIN ANALYZE SELECT pid,product_name,type,country,date,size,cocom,description,egpl_date,ST_AsGeoJSON(outline, 10, 2) AS outline
FROM portal.catalog_full AS cat
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.2200927734375 51.38031005859375, 18.65478515625 51.38031005859375, 18.65478515625 48.7298583984375, 21.2200927734375 48.7298583984375, 21.2200927734375 51.38031005859375))'), cat.outline)
AND (cat.type in ('CADRG','CIB10','DTED1','DTED2'))
EXPLAIN ANALYZE
pour la requête.