[PostgreSQL] Requête peu couteuse ?

Requête peu couteuse ? [PostgreSQL] - SQL/NoSQL - Programmation

Marsh Posté le 19-04-2005 à 17:25:46    

Bonjour!
 
J'ai une expérience plutôt nulle en optimisation de base de données. J'aimerais quelques informations.
 
J'ai une table T de 340k lignes (ca peut facilement dépasser le million).
J'ai un champs D de la forme AAAAMMJJ.
Seulement en fait je n'ai que 2 années différentes.
 
Comment je pourrais récupérer efficacement ces deux années ?
Rien qu'un "select distinct" sur le champs D prend 3.8 secondes et me retourne 731 lignes (forcément: 2x365)
 
Bricoler un "select distinct" sur les 4 premiers caractères du champ D, c'est envisageable ?
 
Pour info je remplis la bd avec un fichier txt structuré. S'il n'y a pas de solution correcte, je vais voir si je peux pas couper le champs D en deux: AAAA && MMJJ  :sweat:  
 
Merci de votre aide.


Message édité par Pwill le 19-04-2005 à 17:59:57
Reply

Marsh Posté le 19-04-2005 à 17:25:46   

Reply

Marsh Posté le 19-04-2005 à 19:48:22    

a priori, je dirais que le plus rapide serait deux requètes, vu ton cas, avec un index sur la date.
select max(D) from T et select min(D) from T

Reply

Marsh Posté le 19-04-2005 à 19:49:14    

mais bon, si tu sais que tu n'as jamais que deux années, faudrait peut-être voir à les hardcoder quelque part ou duppliquer l'information.

Reply

Marsh Posté le 19-04-2005 à 20:20:26    

stock avec un format numérique. pas texte

Reply

Marsh Posté le 19-04-2005 à 20:43:44    

on peut supposer que c'est déjà le cas :o (n'est-ce pas? :sweat: )

Reply

Marsh Posté le 20-04-2005 à 09:11:40    

Merci à vous  :jap:
 
int4 pour la date.
 
Actuellement il se trouve que je n'ai que 2 années différentes, seulement ca peut atteindre une dizaine.
 
Pour le moment c'est moi qui ajoute les données dans la table avec un COPY FROM. Je ferai surement un script d'ajout pour l'utilisateur final.
 
Bon je suppose que le mieux est de mettre ces quelques années dans une table, l'utilisateur devra les rajouter si besoin.


Message édité par Pwill le 20-04-2005 à 09:13:05
Reply

Marsh Posté le 20-04-2005 à 09:14:50    

m'enfin, pourquoi un int4?! c'est pas fait pour ça :/

Reply

Marsh Posté le 20-04-2005 à 11:14:21    

ben ça rentre très bien. tu peux stocker en pseudo DCB
 
4 * 4 bits : année
2 * 4 bits : mois
2 * 4 bits : jour

Reply

Marsh Posté le 20-04-2005 à 12:16:46    

Le plus efficace serait de rajouter un champs avec uniquement l'année dedans, malgré le fait qu'il y aura duplication de données.


---------------
MZP est de retour
Reply

Marsh Posté le 20-04-2005 à 12:39:59    

cinocks a écrit :

Le plus efficace serait de rajouter un champs avec uniquement l'année dedans, malgré le fait qu'il y aura duplication de données.


 
oui, parfois il faut oublier la théorie et songer a la pratique... une ptite duplication de données peut entrainer une hausse significative des perfs...

Reply

Marsh Posté le 20-04-2005 à 12:39:59   

Reply

Marsh Posté le 20-04-2005 à 13:54:45    

tout à fait, la normalisation n'est pas synonyme de performance. Dernormaliser, c'est efficace quand c'est bien pensé.


---------------
MZP est de retour
Reply

Marsh Posté le 20-04-2005 à 14:06:13    

De toute façon, ce qui plombe les perfs, c'est le TABLE SCAN imposé par la recherche des DISTINCT.
 

Code :
  1. SELECT DISTINCT SUBSTR(D, 0, 4) FROM T;


 
(Oracle like)
 
Avoir l'année dans un champ à part va pas changer grand chose, y a toujours obligation de faire un TABLE SCAN.
 
Le seul moyen de réduire la durée d'exécution serait de maintenir dans une table à part par exemple, la liste des différentes années utilisées ... mais ça suppose de vérifier avant chaque ajout/update dans la table T si l'année existe dans cette table à part, etc. (donc une perte de perfs lors du remplissage de la table T).

Reply

Marsh Posté le 20-04-2005 à 14:19:27    

pourquoi pas sous forme numérique ?
 
select ... FROM T where date > 20020000;
 
?

Reply

Marsh Posté le 20-04-2005 à 14:19:35    

Je ne suis pas l'auteur de la structure de la base.  
INT4, j'ai laissé comme c'était.
Je vais opter pour une table contenant les années, car une fois les données insérées, elles sont seulement lues, il n'y a pas un besoin de modification. Et l'insertion se fera de l'ordre d'une fois par an je suppose.
Un script à l'insertion fera ce qu'il faut pour éventuellement ajouter les années concernées. Cette perte de temps n'est pas importante.
 
Merci à vous. :jap:


Message édité par Pwill le 20-04-2005 à 14:23:16
Reply

Marsh Posté le 21-04-2005 à 11:45:54    

moi perso, je préfère laisser de côté les perfs et pensé à la lisibilité :
 
select distinct to_char(to_date(d, 'YYYYMMDD', 'YYYY') from latable
 
Au moins on comprends ce qu'on fait. Et d'un point de vue perfs, tu dois avec 2 ms d'écart par rapport à un substr() classique.
 
PS: par contre, le choix du INT c'est total n'importe quoi. une date, c'est soit un type date, soit un char(8), ça évite de se prendre des cast dans tous les sens au premier traîtement sur les dates :o

Reply

Marsh Posté le 21-04-2005 à 14:05:44    

int(10) et timestamp


Message édité par cinocks le 21-04-2005 à 14:05:52

---------------
MZP est de retour
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed