IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Un DBMS_RANDOM pas si "random" que ça? [FAQ]


Sujet :

SQL Oracle

  1. #1
    Membre régulier Avatar de Dennis Nedry
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 78
    Points : 88
    Points
    88
    Par défaut Un DBMS_RANDOM pas si "random" que ça?
    Bonjour.

    je suis actuellement en train de tester un nouvel outil de Report, et je me suis attaqué à la partie "gestion des gros volumes de données".

    Pour ce faire, j'utilise Oracle 10G Express edition.

    J'ai, au préalable, créé 3 million de lignes sous excel, exportées dans Oracle via Access (qui mettait 20 minutes pour charger 1 malheureux million de lignes... )

    Puis, j'ai démultiplié ces lignes sous Oracle, avec un code SQL tout simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Insert Into SALES(CLIENT_ID,EMPLOYEE_ID,YEAR,MONTH,SALES)
    SELECT CLIENT_ID, DBMS_RANDOM.VALUE(150,179) AS EMPLOYEE_ID, YEAR+3 AS YEAR, MONTH, DBMS_RANDOM.VALUE(0,200)
    FROM SALES;
    DBMS_RANDOM sert à deux moments: pour générer le CA du client, et pour générer le numéro du commercial en charge du client.

    Bref, en partant de 3 millions de lignes, j'ai démultiplié le tout pour arriver à 22,4 millions de lignes.

    J'ouvre mon merveilleux outil de report, et, oh stupeur, que vois-je apparaître:



    On observe que tous les commerciaux sont assez bien répartis, sauf 2 d'entre eux: les numéros 150 et 179, mes deux valeurs extrêmes.

    Si on omet les 3 premières années (générées sous Excel, puis démultipliées sous Oracle pour gonfler les résultats), on remarque que les 2 valeurs extrèmes tombent exactement 50% de fois moins que les autres valeurs. Et chaque année correspond à environ 2 millions d'observations au total, donc le test est infaillible.

    Est-ce normal? Sinon, comment y remédier?

  2. #2
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Il me semble que les bornes ne sont jamais atteintes et que le dbms_random te renvoie un nombre à plusieurs décimales.

    Donc c'est normal, vu que tu fais un Arrondi du nombre (implicite dans ton code).

    Pour avoir 0, il faut que ça te renvoie de 0 à 0.499999
    Pour avoir 1, il faut de 0.5 à 1.49999
    ...
    Pour avoir 179, il faut de 178.50 à 179

  3. #3
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Pour avoir de bonnes données, fais un trunc de ton résultat (avec max +1)

    exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TRUNC(dbms_random.value(0, 180))
    de 0 à 0.99999 => 0
    de 1 à 1.99999 => 1
    de 179 à 179.999999 => 179

    Donc l'écart de chiffres est identique par code

  4. #4
    Membre régulier Avatar de Dennis Nedry
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 78
    Points : 88
    Points
    88
    Par défaut
    j'avais présent à l'esprit cette idée, mais je pensais que Oracle faisait déjà l'arrondi correctement... une peu comme un ALEA.ENTRE.BORNES() de Excel...

    Bon, je teste vos conseils et je vous tiens au courant!

  5. #5
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Tiens nous au courant, c'est un bon sujet et avec tes 3M lignes c'est un super test.

  6. #6
    Membre régulier Avatar de Dennis Nedry
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 78
    Points : 88
    Points
    88
    Par défaut
    C'est bon! tout fonctionne impeccablement.

    la syntaxe à utiliser est donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO SALES(CLIENT_ID,EMPLOYEE_ID,YEAR,MONTH,SALES)
    SELECT CLIENT_ID, TRUNC(dbms_random.value(150, 180)) AS EMPLOYEE_ID, YEAR+3 AS YEAR, MONTH, DBMS_RANDOM.VALUE(0,200)
    FROM SALES;
    Encore merci!

    Citation Envoyé par McM Voir le message
    Tiens nous au courant, c'est un bon sujet et avec tes 3M lignes c'est un super test.
    Eh bien je vais te rassurer: je voulais faire un gros test de charge, donc j'ai pris la liberté de monter jusqu'à 90 millions de lignes . Je l'ai fait avant et après la correction du problême, comme ça on peut avoir une bonne base de test (et éventuellement, si quelqu'un pouvait l'ajouter aux FAQ, ce serait parfait!).


    Sur un échantillon de 89 760 000 individus, En utilisant la fonction dbms_random.value(150, 179):



    Les valeurs extrêmes sont sélectionnées 50% moins que les autres.

    Et maintenant, avec TRUNC(dbms_random.value(150, 180))



    la distribution est bien équirépartie.


    En tout cas, un énorme

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo