Ho una tabella con 50.000 righe. In realtà è una tabella PostGIS.
La query ha 4 parti (1 obbligatoria) (3 Opzionale)
- casella di intersezione (un rettangolo geografico) con 4 lat, long (io uso st_intersects) [Obbligatorio]
- Intervallo di date (min, max) su un campo data
- Tipo di file (un insieme di un massimo di 8 valori di testo) che attualmente utilizza IN (.....) ma se necessario posso creare una tabella temporanea. Vedo che a molte persone non piace IN.
- Paese (un valore di testo).
Mi aspetto circa 100 - 4.000 righe restituite
Se creo un indice composto sulla tabella, quale colonna dovrei usare per prima. La grana fine è probabilmente la posizione (i dati sono diffusi in tutto il mondo). Attualmente lo ho come indice GIST.
Gli altri indici sarebbero BTREE.
La mia intuizione dice che usare grana fine, e ovviamente ultimo. Ad esempio, ci sono solo circa 12 tipi di file, quindi sarebbe molto grande per l'indice.
Cosa dicono i guru PostgreSQL e PostGIS (che conoscono gli interni del sistema)?
AGGIORNARE:
Vorrei affinare questa domanda.
- Non voglio che nessuno debba fare il lavoro che dovrei fare. Rispetto troppo il tuo tempo. Quindi passerò alla spiegazione dell'analisi più avanti.
- Tutto quello che cercavo erano alcuni suggerimenti, consigli e linee guida.
- Ho letto questo eccellente post: https://devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintain-indexes sugli indici
- Quello che faccio normalmente è creare 4 indici separati (geo-box, nome del paese, tipo_file e data) ma cosa voglio vedere cosa farebbe una query composita.
Dimmi se qualcuno di questi presupposti è sbagliato. (Sono abbastanza nuovo all'idea di indici composti)
- L'ordine è importante. Scegli come primo indice quello che ridurrà maggiormente le righe (nel mio caso la posizione (geografia) che è un semplice poligono o poligono farebbe il meglio).
- A volte le query salteranno gli indici. Ma se creo una query composta con chiave (# 1, # 2, # 3, # 4), anche se l'utente crea qualcosa che richiede # 1, # 3, il planner utilizzerà comunque la singola query composita, poiché ordinano è mantenuto.
- Normalmente creerei tre query BTREE e una GIST (per il tipo di geografia). PostGIS non supporta la creazione di un composto di più tipi di indice. Quindi dovrò usare GIST l'indice composto. Ma ciò non dovrebbe ferire le cose.
- Se creo alcuni indici composti o di valore singolo, il planner è abbastanza intelligente da scegliere quello più intelligente .....
- Il nome del paese può avere circa 250 valori diversi ed è ovviamente fortemente legato alla posizione (geobox), ma se il prossimo indice migliore per ridurre la dimensione della riga è file_type, dovrei usarlo successivamente. Non mi aspetto che gli utenti utilizzino spesso il Paese o la data nei loro set di query.
- Non devo preoccuparmi di creare un indice composto di 4 chiavi aumenterà notevolmente la dimensione dei dati dell'indice. Vale a dire se un indice a una chiave sarebbe il 90% dell'aumento delle prestazioni, non fa male aggiungere altri 3 elementi per renderlo composto. Al contrario, dovrei davvero creare entrambi gli indici. Un indice geografico singolo, e anche un indice composto, e lascia che il pianificatore capisca qual è il migliore, e terrà conto della dimensione della tabella dell'indice.
Ancora una volta, non sto chiedendo a nessuno di progettare la mia soluzione, non mi preoccupo del lavoro degli altri. Ma ho bisogno di cose che la documentazione di PostGreSQL non mi dice dell'implementazione
[Il motivo per cui non ho ancora un risultato EXPLAIN da mostrare è che devo creare questa tabella di righe da 25 KB da una tabella di righe da 24 milioni. Ci vuole più tempo di quanto pensassi. Sto raggruppando le cose in 1.000 gruppi di articoli e lascio che l'utente esegua una query sulla tabella delle righe da 25 KB. Ma la mia prossima domanda riguarderà l'uso dei risultati di quella query per andare alla tabella delle righe MASTER 25M ed estrarre le cose, ed è qui che le prestazioni dell'indice composto colpiranno davvero].
query di esempio di seguito:
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')) ;
SPIEGARE i risultati ANALISI (non ho inserito alcun indice composto e dalla velocità che vedo non so se ne ho bisogno).
"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
per la query.