Performance sur les dates ? - SQL/NoSQL - Programmation
Marsh Posté le 04-04-2007 à 18:31:34
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
Fait des benchs
Marsh Posté le 04-04-2007 à 22:16:28
couak a écrit : c'est pas les mêmes requêtes |
Tu penses que je n'aurais pas le même résultat avec ces deux requêtes ?
Marsh Posté le 05-04-2007 à 00:18:59
allez je suis d'une âme généreuse ce soir rien ne vaut la pratique et les tests
Code :
|
Une idée du problème ? Moi j'en ai une :
Code :
|
Toujours pas d'idée ?
Code :
|
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
Sinon tu peux t'amuser à utiliser un BETWEEN plutôt que d'encapsuler dans des <= et > c'est plus lisible
Marsh Posté le 05-04-2007 à 10:03:54
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 !
Marsh Posté le 05-04-2007 à 11:03:01
ReplyMarsh Posté le 05-04-2007 à 21:30:46
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 ?!
Marsh Posté le 06-04-2007 à 00:07:36
ReplyMarsh Posté le 06-04-2007 à 08:53:46
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... ?
Marsh Posté le 06-04-2007 à 09:55:28
chuis d'accord avec pikti. le souci du between, c'est que ça va donner un résultat faux .
Marsh Posté le 10-04-2007 à 09:51:27
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 ?
Marsh Posté le 10-04-2007 à 13:00:39
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)
Marsh Posté le 11-04-2007 à 10:22:36
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
Marsh Posté le 13-04-2007 à 00:10:13
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.
Marsh Posté le 13-04-2007 à 09:28:43
et il va éviter d'utiliser l'éventuel index... dans un sujet sur les performances c'est moyen
Marsh Posté le 13-04-2007 à 10:22:01
orafrance a écrit : et il va éviter d'utiliser l'éventuel index... dans un sujet sur les performances c'est moyen |
Code :
|
Marsh Posté le 13-04-2007 à 14:02:33
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
Marsh Posté le 13-04-2007 à 14:12:10
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)
Marsh Posté le 13-04-2007 à 14:23:46
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
Marsh Posté le 13-04-2007 à 15:40:41
casimimir a écrit : faut voir pour l'index degueu... ca peut parfois se justifier |
une date c'est précis à la seconde prêt alors si tu elèves 1/3600*24 çà suffit
Marsh Posté le 13-04-2007 à 18:23:29
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
Marsh Posté le 16-04-2007 à 11:45:30
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
Marsh Posté le 16-04-2007 à 14:15:28
ha oui, en effet, le résultat est le même mais pas le temps de le voir
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
Marsh Posté le 16-04-2007 à 14:22:17
Quelle merde Oracle
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.
Marsh Posté le 16-04-2007 à 14:30:40
Après tests, c'est tout comme j'ai dit
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 ) - c pourtant le cas le plus simple
select *
from tstround
where round(num, 0) between 1 and 3
PE :
SELECT : 0%
Index Scan : 100%
(faut pas chercher à comprendre )
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)
Marsh Posté le 16-04-2007 à 14:44:26
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)
Marsh Posté le 16-04-2007 à 16:28:50
les plans d'exécution sous SQL-Server stro laid
Sinon, en effet, parfois Oracle est moins bon... faut bien laisser la place à l'amélioration sinon comment vendre les versions suivantes
Marsh Posté le 16-04-2007 à 17:15:55
moi je les aime bien les PE de SQL Server. c'est mieux que les listings que t'as sous SQL+
je trouve à bien lisible moi (pis quand tu passes la papatte dessus, t'as plein d'infos en plus)
Marsh Posté le 17-04-2007 à 11:22:57
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
Marsh Posté le 04-04-2007 à 17:32:36
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.