Compte tenu du tableau:
Column | Type
id | integer
latitude | numeric(9,6)
longitude | numeric(9,6)
speed | integer
equipment_id | integer
created_at | timestamp without time zone
Indexes:
"geoposition_records_pkey" PRIMARY KEY, btree (id)
Le tableau compte 20 millions d'enregistrements, ce qui n'est pas, relativement parlant, un grand nombre. Mais cela ralentit les analyses séquentielles.
Comment puis-je obtenir le dernier enregistrement ( max(created_at)
) de chacun equipment_id
?
J'ai essayé les deux requêtes suivantes, avec plusieurs variantes que j'ai lues à travers de nombreuses réponses de ce sujet:
select max(created_at),equipment_id from geoposition_records group by equipment_id;
select distinct on (equipment_id) equipment_id,created_at
from geoposition_records order by equipment_id, created_at desc;
J'ai également essayé de créer des index btree pour equipment_id,created_at
mais Postgres trouve que l'utilisation d'un seqscan est plus rapide. Le forçage enable_seqscan = off
n'est d'aucune utilité non plus, car la lecture de l'index est aussi lente que le scan séquentiel, probablement pire.
La requête doit être exécutée périodiquement en renvoyant toujours la dernière.
Utiliser Postgres 9.3.
Expliquez / analysez (avec 1,7 million d'enregistrements):
set enable_seqscan=true;
explain analyze select max(created_at),equipment_id from geoposition_records group by equipment_id;
"HashAggregate (cost=47803.77..47804.34 rows=57 width=12) (actual time=1935.536..1935.556 rows=58 loops=1)"
" -> Seq Scan on geoposition_records (cost=0.00..39544.51 rows=1651851 width=12) (actual time=0.029..494.296 rows=1651851 loops=1)"
"Total runtime: 1935.632 ms"
set enable_seqscan=false;
explain analyze select max(created_at),equipment_id from geoposition_records group by equipment_id;
"GroupAggregate (cost=0.00..2995933.57 rows=57 width=12) (actual time=222.034..11305.073 rows=58 loops=1)"
" -> Index Scan using geoposition_records_equipment_id_created_at_idx on geoposition_records (cost=0.00..2987673.75 rows=1651851 width=12) (actual time=0.062..10248.703 rows=1651851 loops=1)"
"Total runtime: 11305.161 ms"
NULL
valeurs dansequipment_id
le pourcentage attendu est en dessous de 0,1%