Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1278 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Performance sur les dates ?

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Performance sur les dates ?

n°1538526
pot2yaourt
Posté le 04-04-2007 à 17:32:36  profilanswer
 

Salut tlm !
 
Voilà, lorsque je fais une requête permettant d'afficher qqs infos contenues dans une table, quelle est la requête la plus performante entre ces deux là (sauf erreur, le résultat retourné étant identique) :
 
Exemple en Oracle :
 
SELECT *
FROM maTable
WHERE champDate >= TO_DATE('20070404','YYYYMMDD')
AND champDate < TO_DATE('20070405','YYYYMMDD')
 
ou
 
SELECT *
FROM maTable
WHERE champDate = TO_DATE('20070404','YYYYMMDD')
 
Question bonus : en supposant qu'une de ces deux requêtes est plus performante que l'autre, fonctionnerait-elle à l'identique sur tous les SGBD (MySQL, SQL Serveur, etc...) ?
 
 
Merci d'avance pour vos réponses !
Lionel.

mood
Publicité
Posté le 04-04-2007 à 17:32:36  profilanswer
 

n°1538570
spark
Luc ?
Posté le 04-04-2007 à 18:31:34  profilanswer
 

A mon avis, ca va etre la deuxième.
Moins de tests à faire sachant que pour déterminer si c'est supérieur ou inférieur, il doit scanner toute la chaine (enfin du début à une certaine position tant que ca matche)
 
Mais je peux me tromper :o
 
Fait des benchs :)

n°1538669
couak
Posté le 04-04-2007 à 21:08:26  profilanswer
 

c'est pas les mêmes requêtes :o

n°1538696
pot2yaourt
Posté le 04-04-2007 à 22:16:28  profilanswer
 

couak a écrit :

c'est pas les mêmes requêtes :o


 
Tu penses que je n'aurais pas le même résultat avec ces deux requêtes ?

n°1538745
couak
Posté le 05-04-2007 à 00:18:59  profilanswer
 

allez je suis d'une âme généreuse ce soir :D rien ne vaut la pratique et les tests

Code :
  1. SQL> create table pouet (champdate date);
  2. Table created.
  3. SQL> insert into pouet values (sysdate);
  4. 1 row created.
  5. SQL> select * from pouet;
  6. CHAMPDATE
  7. ---------
  8. 05-APR-07
  9. SQL> select * from pouet where champdate>=to_date('20070405','YYYYMMDD') and champdate<to_date('20070406','YYYYMMDD');
  10. CHAMPDATE
  11. ---------
  12. 05-APR-07
  13. SQL> select * from pouet where champdate=to_date('20070405','YYYYMMDD');
  14. no rows selected


 
Une idée du problème ? Moi j'en ai une :

Code :
  1. SQL> select to_char(champdate, 'DD/MM/YYYY HH24:MI:SS') from pouet;
  2. TO_CHAR(CHAMPDATE,'
  3. -------------------
  4. 05/04/2007 00:12:14
  5. SQL> select to_char(to_date('20070405','YYYYMMDD'), 'DD/MM/YYYY HH24:MI:SS') from dual;
  6. TO_CHAR(TO_DATE('20
  7. -------------------
  8. 05/04/2007 00:00:00


 
Toujours pas d'idée ?

Code :
  1. SQL> select champdate-to_date('20070405','YYYYMMDD') from pouet;
  2. CHAMPDATE-TO_DATE('20070405','YYYYMMDD')
  3. ----------------------------------------
  4.                                .00849537


Tu as une différence de 0,00849537 jour entre la donnée dans la table pouet, et le 05/04/2007 à minuit, et donc tes requêtes ne sont pas les mêmes car tu es tombé dans le piège des dates sous Oracle :o
Sinon tu peux t'amuser à utiliser un BETWEEN plutôt que d'encapsuler dans des <= et > c'est plus lisible


Message édité par couak le 05-04-2007 à 00:19:48
n°1538811
pot2yaourt
Posté le 05-04-2007 à 10:03:54  profilanswer
 

Ok, donc si je comprends bien, en faisant :
 
SELECT *
FROM maTable
WHERE champDate = TO_DATE('20070404','YYYYMMDD')
 
Il va ma ramener uniquement les lignes où champDate est égale exactement à '20070404000000'.
 
Je pensais qu'il allait me renvoyer toutes les lignes commençant par '20070404'  :(  
 
Bon, ben en tous cas merci d'avoir pris un peu de ton temps pour m'expliquer tout ça !
C'est super sympa !


Message édité par pot2yaourt le 05-04-2007 à 10:04:22
n°1538834
orafrance
Posté le 05-04-2007 à 11:03:01  profilanswer
 

like au lieu de égale dans ce cas mais BETWEEN est préférable :)

n°1539255
pot2yaourt
Posté le 05-04-2007 à 21:30:46  profilanswer
 

orafrance a écrit :

like au lieu de égale dans ce cas mais BETWEEN est préférable :)


 
Donc, pour résumer, la bonne méthode pour faire des tris sur les dates :
 
SELECT *
FROM maTable
WHERE champDate BETWEEN TO_DATE('20070405','YYYYMMDD')
AND TO_DATE('20070406','YYYYMMDD')
 
J'ai juste ?!

n°1539297
couak
Posté le 05-04-2007 à 23:32:15  profilanswer
 

bon encore une fois : as-tu essayé ?

n°1539314
Taz
bisounours-codeur
Posté le 06-04-2007 à 00:07:36  profilanswer
 

je vois pas la différence entre > and < et between. Un SGBD à la con peut être

mood
Publicité
Posté le 06-04-2007 à 00:07:36  profilanswer
 

n°1539369
pot2yaourt
Posté le 06-04-2007 à 08:53:46  profilanswer
 

couak a écrit :

bon encore une fois : as-tu essayé ?


 
Ben oui, je viens d'essayer et ça fonctionne : ça me ramène bien le même nombre de lignes.
 
Par contre, je n'ai pas vu de différence de temps entre >= < et BETWEEN... sous Oracle hein ! P't'être qu'il y a une différence notable sur du MySQL ou SQL Serveur... ?

Message cité 1 fois
Message édité par pot2yaourt le 06-04-2007 à 08:55:08
n°1539370
pikti
I’ve done worse
Posté le 06-04-2007 à 08:55:38  profilanswer
 

ouaip, between c'est >= <= :)

n°1539390
MagicBuzz
Posté le 06-04-2007 à 09:55:28  profilanswer
 

chuis d'accord avec pikti. le souci du between, c'est que ça va donner un résultat faux :/.

n°1540594
orafrance
Posté le 10-04-2007 à 09:51:27  profilanswer
 

Taz a écrit :

je vois pas la différence entre > and < et between. Un SGBD à la con peut être


 
il n'y a pas de différence ;)
 

MagicBuzz a écrit :

chuis d'accord avec pikti. le souci du between, c'est que ça va donner un résultat faux :/.


 
bah non, pourquoi ?  :heink:

n°1540703
MagicBuzz
Posté le 10-04-2007 à 13:00:39  profilanswer
 

ben si. between ça fait >= et <=
 
donc avec l'exemple, le between entre le 01/01/2000 et le 02/01/2000 pour récupérer les élément au 01/01/2000, ça fait faire du 01/01/2000 00:00:00 au 02/01/2000 00:00:00 inclus.
=> donc si j'un un élément enregistré au 02/01/2000 00:00:00, il ne doit pas être retourné, mais le serva par le between.
Et le problème d'un champ datetime, c'est qu'on va vite fait d'enregister des dates uniquement, sans l'heure (et donc se heurter systématiquement à ce problème, puisqu'une date dans un datetime, c'est la date à minuit pile)

n°1541115
orafrance
Posté le 11-04-2007 à 08:35:11  profilanswer
 

évidemment il faut adapter les bornes  :D

n°1541159
pikti
I’ve done worse
Posté le 11-04-2007 à 10:22:36  profilanswer
 

pot2yaourt a écrit :

Par contre, je n'ai pas vu de différence de temps entre >= < et BETWEEN


 

pikti a écrit :

between c'est >= <= :)


 
 
C'était juste pour rectifier une affirmation erronée  :jap:

n°1541166
MagicBuzz
Posté le 11-04-2007 à 10:32:08  profilanswer
 

genre, le truc que j'ai expliqué 2 lignes plus haut :ange:

n°1541760
orafrance
Posté le 12-04-2007 à 09:30:39  profilanswer
 

ouais c'est trop injuste :/
 
:D

n°1542332
Beegee
Posté le 13-04-2007 à 00:10:13  profilanswer
 

Une autre possibilité :
 
SELECT *
FROM maTable
WHERE TRUNC(champDate) = TO_DATE('20070404','YYYYMMDD');
 
Le TRUNC va renvoyer la partie date uniquement, ce qui revient à mettre l'heure à minuit.

n°1542383
orafrance
Posté le 13-04-2007 à 09:28:43  profilanswer
 

et il va éviter d'utiliser l'éventuel index... dans un sujet sur les performances c'est moyen :D

n°1542411
couak
Posté le 13-04-2007 à 10:22:01  profilanswer
 

orafrance a écrit :

et il va éviter d'utiliser l'éventuel index... dans un sujet sur les performances c'est moyen :D


Code :
  1. create index index_degueux on matable (trunc(champdate));

[:zerod]

n°1542428
orafrance
Posté le 13-04-2007 à 10:37:26  profilanswer
 

le nom est bien choisi en effet :D

n°1542628
casimimir
Posté le 13-04-2007 à 14:02:33  profilanswer
 

faut voir pour l'index degueu... ca peut parfois se justifier
 
sinon un between trunc(ma_date) and (trunc(ma_date)+0.99999999999999999999) ca devrait le faire, faut voir le détail de définition de tes valeurs
 
mais >= trunc(ma_date) and <trunc(ma_date)+1 jcrois pas que oracle le gérerai mal

n°1542632
Beegee
Posté le 13-04-2007 à 14:12:10  profilanswer
 

S'il y a un index sur champDate :
 
SELECT *
FROM maTable
WHERE champDate BETWEEN TO_DATE('20070404','YYYYMMDD') AND TO_DATE('20070404 235959','YYYYMMDD HH24MISS')
 
ou encore
 
 
SELECT *
FROM maTable
WHERE champDate BETWEEN TO_DATE('20070404','YYYYMMDD') AND TO_DATE('20070404','YYYYMMDD') + 1 - 1/(24*3600)

n°1542643
couak
Posté le 13-04-2007 à 14:23:46  profilanswer
 

vous vous faites des noeuds au cerveau pour pas grand chose :/ vous êtes en train d'essayer de gratter 1/4 de cycle de processeur

n°1542688
orafrance
Posté le 13-04-2007 à 15:40:41  profilanswer
 

casimimir a écrit :

faut voir pour l'index degueu... ca peut parfois se justifier
 
sinon un between trunc(ma_date) and (trunc(ma_date)+0.99999999999999999999) ca devrait le faire, faut voir le détail de définition de tes valeurs
 
mais >= trunc(ma_date) and <trunc(ma_date)+1 jcrois pas que oracle le gérerai mal


 
une date c'est précis à la seconde prêt alors si tu elèves 1/3600*24 çà suffit :)

n°1542764
MagicBuzz
Posté le 13-04-2007 à 18:23:29  profilanswer
 

avec sql server c'est quand même plus simple... tu fais un round(ladate,0) et tu bosses qu'avec la partie date.
et vu que la date est un float, le round n'impacte pas l'utilisation des index :D

n°1543199
orafrance
Posté le 16-04-2007 à 09:55:34  profilanswer
 

TRUNC fait pareil :D

n°1543252
MagicBuzz
Posté le 16-04-2007 à 11:45:30  profilanswer
 

ben alors pkoi tu dis qu'il utilise pas les index ?
normalement il devrait, puisque le trunc ne peut pas changer l'ordre des données :??:

n°1543325
orafrance
Posté le 16-04-2007 à 14:15:28  profilanswer
 

ha oui, en effet, le résultat est le même mais pas le temps de le voir :D
 
sous Oracle, quelque soit la fonction appliquée à une colonne inhibe l'usage de l'index... éventuellement, il faut créer un index de fonction ;)

n°1543327
MagicBuzz
Posté le 16-04-2007 à 14:22:17  profilanswer
 

Quelle merde Oracle :D
 
Sous SQL Server, ça dépend de la fonction.
Si SQL Server détecte que l'ordre de tri n'est pas impacté par la fonction, alors il effectue la requête sur l'index en fonction des données passées en paramètre, puis applique la fonction sur le résultat du filtre.
 
Donc à priori, le Round ne pose pas de problème.
 
Là où il peut poser problème, c'est sur un sous-tri après le round :  
 
col1 col2
1,2 A
1,1 B
 
=> order by col1, col2 retourne les lignes dans l'ordre "B", "A"
=> order by round(col1, 0), col2 retourne les lignes dans l'ordre "A", "B"
 
Il faudra vérifier le plan d'exécution sur pour ce type de requête. A mon avis l'index est utilisé une première fois, puis un filtre sans index est effectué sur le résultat final. Performances dégradées donc, mais dans le cas d'un between ça ne devrait pas poser de problème.


Message édité par MagicBuzz le 16-04-2007 à 14:23:01
n°1543330
MagicBuzz
Posté le 16-04-2007 à 14:30:40  profilanswer
 

Après tests, c'est tout comme j'ai dit :D
 
Structure de la table de test :
create table TSTROUND (num as numeric(18,9), val as varchar(50))
create index TSTROUND_IX on TSTROUND (num, val)
 
 
select *
from tstround
order by round(num, 0), val
 
PE :
SELECT 0%
SORT 78%
Compute Scalar 0%
Index Scan 22%
 
=> C'est donc bien ça : l'index est appelé pour dégrossir le travail, puis les données sont re-triées à la main
 
select *
from tstround
order by num, val
 
PE :
SELECT : 0%
Index Scan : 100%
(sans surprise)
 
select *
from tstround
where num between 1 and 3
 
PE : (partage en live total :pt1cable:) - c pourtant le cas le plus simple :D
http://magicbuzz.multimania.com/files/partageenlive.png
 
select *
from tstround
where round(num, 0) between 1 and 3
 
PE :
SELECT : 0%
Index Scan : 100%
(faut pas chercher à comprendre :D)
 
select *
from tstround
where round(num, 0) between 1 and 3
order by round(num, 0), val
 
PE :
SELECT 0%
SORT 78%
Compute Scalar 0%
Index Scan 22%
(le même que le premier)


Message édité par MagicBuzz le 16-04-2007 à 14:45:20
n°1543336
MagicBuzz
Posté le 16-04-2007 à 14:44:26  profilanswer
 

Edit : En fait, c'est pas trop un partage en live la capture d'écran...
 
Vu qu'on ne passe pas par round(), il est capable à partir des constantes passées au between d'isoler exactement la partie de l'index correspondant à l'ensemble de valeurs (c'est donc effectivement bien plus performant que le Index Scan qui nécessite de se pallucher tout l'index. Cependant, on voit bien que SQL Server est tout de même capable d'analyser l'index lorsqu'on passer par une fonction)


Message édité par MagicBuzz le 16-04-2007 à 14:47:46
n°1543398
orafrance
Posté le 16-04-2007 à 16:28:50  profilanswer
 

les plans d'exécution sous SQL-Server stro laid :D
 
Sinon, en effet, parfois Oracle est moins bon... faut bien laisser la place à l'amélioration sinon comment vendre les versions suivantes  :whistle:


Message édité par orafrance le 16-04-2007 à 16:29:29
n°1543427
MagicBuzz
Posté le 16-04-2007 à 17:15:55  profilanswer
 

moi je les aime bien les PE de SQL Server. c'est mieux que les listings que t'as sous SQL+ :p
 
je trouve à bien lisible moi (pis quand tu passes la papatte dessus, t'as plein d'infos en plus)


Message édité par MagicBuzz le 16-04-2007 à 17:16:06
n°1543668
orafrance
Posté le 17-04-2007 à 11:22:57  profilanswer
 

tu as la même chose sous Oracle, il suffit d'utiliser la console d'admin livrée avec Oracle client ou SQL Developper encore gratuit pour l'instant :)


Message édité par orafrance le 17-04-2007 à 11:23:10
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Performance sur les dates ?

 

Sujets relatifs
Modification de dates EXE et antivirusNombre de mois différents par rapport a des dates
question sur les dates[exel\calc]comparaison de dates ?!
Selectionner des semaines avec leurs intervalles de dates[SQL] Indicateur de performance pour une base Oracle
Programme calculant la difference entre 2 datesModification des dates d'une table mysql
Requête *entre deux datesDifférence de performance entre Access et SQL Server ?
Plus de sujets relatifs à : Performance sur les dates ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR