PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : Général » Accumulateur sur une suite d'enregistrement » 07/10/2010 10:14:00

Bonjour,

J'ai effectué des tests de charges en insérant 100 000 records dans ma table de positions :
- requête 1 : sur l'intégralité des données de la vue : 4 min 30
- requête 2 : sur un véhicule dans la vue : 9 s
Ensuite j'ai suivi votre conseil avec un index sur (pvehicleId, ptime) :
- requête 1 : 3 s
- requête 2 : 130 ms
Conclusion : sans commentaire

Voici l'index créé :
CREATE INDEX veh_time_index
  ON positions
  USING btree
  (ptime, pvehicleid);

Est-ce correct ? je ne sais pas ce que signifie btree.

Dois je créé un index sur ptime seul et sur pvehicleId seul ? quel est l'impact ?

Merci encore pour vos conseils avisés.

Phil

#2 Re : Général » Accumulateur sur une suite d'enregistrement » 06/10/2010 09:25:25

Bonjour,

J'ai modifié la vue pour prendre en plus le véhicule, la vue devient donc :

CREATE VIEW journeyView AS
SELECT VehicleId, BeginDate, (journeyComputed).journeyEndDate AS EndDate, (journeyComputed).mileage AS Mileage
FROM (SELECT pvehicleId as VehicleId, ptime AS BeginDate, compute_journey(ptime, pvehicleId) AS journeyComputed
FROM Positions WHERE pstate = 'Start') AS tmp;

En faisant quelques explain sur les requêtes :

1) Requête sur une date et un véhicule : explain select * from journeyView where BeginDate='2010-10-04 12:00:00' and VehicleId ='1';
"Subquery Scan on tmp  (cost=0.00..31.79 rows=1 width=44)"
"  ->  Seq Scan on positions  (cost=0.00..31.78 rows=1 width=12)"
"        Filter: ((pstate = 'Start'::state) AND (ptime = '2010-10-04 12:00:00'::timestamp without time zone) AND (pvehicleid = 1))"

2) Requête uniquement sur une date : explain select * from journeyView where BeginDate='2010-10-04 12:00:00';
"Subquery Scan on tmp  (cost=0.00..28.71 rows=1 width=44)"
"  ->  Seq Scan on positions  (cost=0.00..28.70 rows=1 width=12)"
"        Filter: ((pstate = 'Start'::state) AND (ptime = '2010-10-04 12:00:00'::timestamp without time zone))"

3) Requête sur l'intégralité de la vue : explain select * from journeyView;
"Subquery Scan on tmp  (cost=0.00..26.93 rows=6 width=44)"
"  ->  Seq Scan on positions  (cost=0.00..26.88 rows=6 width=12)"
"        Filter: (pstate = 'Start'::state)"

Je ne sais pas bien interpréter ces résultats, mais apparemment il filtre d'abord et exécute la vue ensuite, est-ce bien cela ?

Merci.

#3 Re : Général » Accumulateur sur une suite d'enregistrement » 05/10/2010 22:43:52

Re-bonsoir,

En fouillant un peu partout des exemples de types composites j'ai essayé avec des parenthèses d'accéder à ce fameux type :

CREATE VIEW journeyView AS
SELECT BeginDate, (journeyComputed).journeyEndDate AS EndDate, (journeyComputed).mileage AS Mileage
FROM (SELECT ptime AS BeginDate, compute_journey(ptime, pvehicleId) AS journeyComputed
FROM Positions WHERE pstate = 'Start') AS tmp;

Dernière question : est-ce bien performant comme principe ? Quels sont les best practices sur le sujet ?

Merci encore pour votre aide.

#4 Re : Général » Accumulateur sur une suite d'enregistrement » 05/10/2010 22:24:38

Bonsoir,

J'ai pu mettre en application tout ceci en rentrant et j'en suis à l'étape 3 : la plus importante.
J'ai donc créé mes tables avec des données, créer une fonction mais je bloque sur la vue avec le "split" des données dans mon type spécifique (avec 2 attributs).

Voici mon type :

CREATE TYPE journey_calculus_type as (journeyEndDate timestamp, mileage integer);

Voici ma fonction :

CREATE OR REPLACE FUNCTION compute_journey(journeyBeginDate timestamp, vehicleId integer)
RETURNS journey_calculus_type AS $$
DECLARE
    next_journey_start_date timestamp;
    result journey_calculus_type%rowtype;
BEGIN
    SELECT ptime INTO next_journey_start_date FROM Positions WHERE pvehicleid=vehicleId AND pstate='Start' AND ptime > journeyBeginDate LIMIT 1;
    SELECT max(ptime),sum(pkms) INTO result FROM Positions where pvehicleid=vehicleId AND ptime >= journeyBeginDate AND ptime < next_journey_start_date;
    RETURN result;
END;
$$ LANGUAGE plpgsql;

Quand je créé ma vue sous la forme :

CREATE VIEW journeyView AS
SELECT BeginDate, journeyComputed.journeyEndDate AS EndDate, journeyComputed.mileage AS Mileage
FROM (SELECT ptime AS BeginDate, compute_journey(ptime, pvehicleId) AS journeyComputed
FROM Positions WHERE pstate = 'Start') AS tmp;

=> Résultat il manque un FROM sur le journeyComputed du premier SELECT

J'ai alors remplacé le premier select par un * (je sais c'est pas très joli mais c'est pour tester), la vue devient donc :

CREATE VIEW journeyView AS
SELECT *
FROM (SELECT ptime AS BeginDate, compute_journey(ptime, pvehicleId) AS journeyComputed
FROM Positions WHERE pstate = 'Start') AS tmp;

=> J'ai bien mes résultat quand je requête cette vue mais la deuxième colonne contient un champs de type "journeyComputed" que je n'arrive pas à séparer.

Merci pour votre aide.

Phil

#5 Re : Général » Accumulateur sur une suite d'enregistrement » 05/10/2010 11:51:15

Merci beaucoup. Dans mon application d'origine je parcourais la table et je créai un identifiant de trajet dès que je détectai un nouveau démarrage.
Votre solution semble plus élégante et c'est directement le SGBD qui gère tout cela, je serai tenté de dire que c'est plus performant.
Pour résumer je dois créer :
- une table avec les historiques (évidement)
- une fonction calcule_trajet qui prend en paramètre une date et un véhicule et qui retourne le km calculé ainsi que la date du dernier événement du trajet
- une vue permettant de tester tout cela
Je vais maquetter cette solution et je reviendrai probablement vers vous, je pensais utiliser la dernière version la 9.0.

Merci encore

#6 Re : Général » Accumulateur sur une suite d'enregistrement » 05/10/2010 10:51:29

Oui c'est tout à fait cela, la table contient l'historique des positions de plusieurs véhicules.

Phil

#7 Re : Général » Accumulateur sur une suite d'enregistrement » 05/10/2010 10:21:38

Bonjour,

Un trajet est défini par la détection d'un démarrage (D), une liste d'événement de conduite (C) et une fin définie par le statut arrêt (A).
En fait dans ma table j'ai une série de : D - C - C - C ... - A - D - C ... - A - C
Pour identifier un trajet il faut parcourir cette liste, prendre le premier D, cumuler les C, et arrêter à un A.
L'identifiant de trajet en tant qu'ID peut être généré automatiquement.

Merci.

#8 Général » Accumulateur sur une suite d'enregistrement » 05/10/2010 10:11:28

philaman
Réponses : 14

Bonjour à tous,

Je suis nouveau sur ce Forum ainsi que sur Postgresql, depuis longtemps je suis limité avec mon ancien SGBD que je ne nommerai pas ici.
Voilà ma problématique : j'ai une table qui contient une liste d'événements horodatés concernant des informations de la localisation de véhicules sous la forme suivante :
Date/ heure ; véhicule ; position (latitude, longitude) ; type d'état ; kilomètre réalisé depuis le dernier arrêt
Le type d'état peut être un des cas suivant : démarrage, conduite, arrêt
J'aimerai savoir si il est possible de créer une vue "Trajet" qui me retourne les informations suivantes :
véhicule ; date/ heure début, date/ heure fin de trajet; kilométrage réalisé
J'ai déjà réalisé ce genre de chose mais avec une application qui va parcourir ma première table et qui à chaque démarrage / arrêt créé un nouveau trajet et compte les kms puis sotcke dans une autre table. L'application fonctionne mais je reste persuadé qu'il est possible de déléguer ce genre de chose directement au SGBDR.
S'agit t-il d'une forme d'accumulateur de somme ou suis-je sur la mauvaise piste ?

Merci beaucoup pour votre aide.

Phil.

Pied de page des forums

Propulsé par FluxBB