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

PL/SQL Oracle Discussion :

Performances : SQL vs PL/SQL


Sujet :

PL/SQL Oracle

  1. #1
    Nouveau Candidat au Club
    Femme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2012
    Messages : 6
    Points : 0
    Points
    0
    Par défaut Performances : SQL vs PL/SQL
    En ce qui concerne la performance, il est préférable d'utiliser l'instruction if-then-else ou la clause where ?
    Merci pour votre reponse

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Ça dépend.

  3. #3
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    Une clause where peut servir à filtrer des données lors de l'accès alors qu'une condition pl/sql va lire toutes les données pour les filtrer ensuite. Donc la réponse serait en faveur du where.
    Cordialement,
    Franck.
    Franck Pachot - Developer Advocate Yugabyte 🚀 Base de Données distribuée, open source, compatible PostgreSQL
    🗣 twitter: @FranckPachot - 📝 blog: blog.pachot.net - 🎧 podcast en français : https://anchor.fm/franckpachot

  4. #4
    Nouveau Candidat au Club
    Femme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2012
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    Je comprends que la clause where charge la mémoire avec les données filtrées tandis que l'instruction if-then else charge la mémoire avec toutes les données, c'est vrai?
    Donc, le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select 
      case when x > 3 then 'ok'
           else 'not ok'
      end action;	
    for r in c loop 
    update.. set.. where.. and  r.action = 'ok'
    est meilleur que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select 
      case when x > 3 then 'ok'
           else 'not ok'
      end action;
    for r in c loop 
    if r.action = 'ok'
    update.. set.. where..
    Merci,
    blackangel

  5. #5
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    select
    case when x > 3 then 'ok'
    else 'not ok'
    end action;
    for r in c loop
    update.. set.. where.. and r.action = 'ok'
     
    est meilleure que :
     
    select
    case when x > 3 then 'ok'
    else 'not ok'
    end action;
    for r in c loop
    if r.action = 'ok'
    update.. set.. where..



    Et dans ton deuxième cas tu mets quoi dans la clause WHERE à ton avis ???
    J'ai pas l'impression que tu aies compris ta propre question !

    La différence porte sur un exemple tel que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    FOR i IN 
      (SELECT col1, col2
      FROM ma_table)
      LOOP
     
      IF (Col2 = 0) THEN
        UPDATE ..
      END IF;
    Et celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    FOR i IN 
      (SELECT col1, col2
      FROM ma_table
      WHERE Col2 = 0)
      LOOP
     
      UPDATE ..
    Le 2eme sera plus performant car le nombre de lignes sélectionnées est conditionné par la clause WHERE, en résulte (normalement) un nombre de lignes moindre à traiter

  6. #6
    Nouveau Candidat au Club
    Femme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2012
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    La situation exacte est le suivante :

    j'ai créé une table log :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    create table log as
    SELECT
    case when date > trunc(sysdate-20) then 'ok'
    else 'not ok'
    end action, *
    from table_y
    Je veux faire update sur la table_y en fonction de chaque cas ( et puis faire update sur log pour voir les cas traités avec succès ou échec).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for r in (select * from log) loop
    if r.action = 'ok'
    update table_y set.. where..
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for r in (select * from log) loop
    update.. set.. where.. and r.action = 'ok'
    Je voudrais savoir si le 2eme est plus performant

  7. #7
    Membre expert

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2012
    Messages
    612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Juin 2012
    Messages : 612
    Points : 3 066
    Points
    3 066
    Par défaut
    Bonjour,

    Citation Envoyé par blackangel_xwing Voir le message
    La situation exacte est le suivante
    Je trouve votre explication encore très imprécise...

    Pourquoi ne mettez-vous pas la condition sur le SELECT (cela serait plus performant) ?

    Expliquez VRAIMENT et COMPLÈTEMENT ce que vous voulez faire, vous aurez une réponse plus rapide et bien plus adaptée à vos besoins.

  8. #8
    Nouveau Candidat au Club
    Femme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2012
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    J'essaie d'être plus explicite

    Je ne peut pas mettre la condition sur le select parce que je necessite de faire update sur table - source en fonction de la condition date > trunc (sysdate-20); j'utilise la table log pour voir les cas traités avec succès/échec et retenir les erreurs en cas d'échec;

    La première tentative a été :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    create table log as
    SELECT  y.*
    from table_source y
     
    for r in (select * from log) loop
    begin
     
    if r.date > trunc(sysdate-20) then 
    	update table_source  y set y.exec ='D' where y.id = r.id
    	update log set obs ='exécuté' where id = r.id
    else
     
    	update table_source  y set y.rej ='D' where y.id = r.id
    	update log set obs ='rejeté' where id = r.id
    end if ;
     
    exception when others then
    		update log set obs ='err' where id = r.id 
    end;
    end loop;
    Mais j'utilisais "select case " parce que je pensais qu'il est plus performant, corrigez-moi si je me trompe ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    create table log as
    SELECT
    case when date > trunc(sysdate-20) then 'ok'
    else 'not ok'
    end action, *
    from table_source y 
     
    -- 1ère version
    for r in (select * from log) loop
    if r.action ='ok' then
    	begin
    		update table_source  y set y.exec ='D' where y.id = r.id
    		update log set obs ='exécuté' where id = r.id
    	exception when others then
    		update log set obs ='err' where id = r.id 
        	end;
    else 
    	begin
    		update table_source  y set y.rej ='D' where y.id = r.id
    		update log set obs ='rejeté' where id = r.id
    	exception when others then
    		update log set obs ='err' where id = r.id 
    	end;
    end if;
    end loop;
     
    --la 2eme
    for r in (select * from log) loop
    begin
    	update table_source  y set y.exec ='D' where y.id = r.id and r.action ='ok'
    	    update log set obs ='exécuté' where id = r.id and r.action ='ok'
    	update table_source  y set y.rej ='D' where y.id = r.id and r.action ='not ok'
    	    update log set obs ='rejeté' where id = r.id and r.action ='not ok'
    exception when others then
            update log set obs ='err' where id = r.id 
    end;
    end loop;
    Quelle version est donc plus performante?

  9. #9
    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 sera toujours moins performant de faire un update qui va updater 0 ligne que de ne pas faire d'update !

    Donc entre ce code qui fait 2 updates dont un qui ne va rien faire mais qu'Oracle va quand même chercher à savoir s'il y a des données
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    UPDATE table_source  y SET y.exec ='D' WHERE y.ID = r.ID AND r.action ='ok'
    UPDATE table_source  y SET y.rej ='D' WHERE y.ID = r.ID AND r.action ='not ok'
    et ce code qui ne fait qu'un seul update suivant une variable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IF r.action = 'ok' 
    THEN 
    	UPDATE table_source  y SET y.exec ='D' WHERE y.ID = r.ID
    ELSE
    	UPDATE table_source  y SET y.rej ='D' WHERE y.ID = r.ID
    END IF;
    C'est forcément le deuxième code.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  10. #10
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    La version la plus performante est celle que vous n'avez pas exploitée, c'est à dire en FULL SQL.

    Votre code est très facilement transposable en commande ensembliste

    PS : A moins que dans votre code il n'y ait des appels à des procédures, fonctions, ou autres tests/manipulations de données que l'on ne peut voir dans votre extrait de code.

  11. #11
    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
    Sauf pour traiter les erreurs au niveau ligne. Imagine qu'il y a un trigger sur table_source qui peut sortir en erreur, un seul update ne serait pas gérable.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  12. #12
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    C'est aussi une possibilité que je n'avais pas envisagée vue la simplicité de la mise à jour.
    Elle est toutefois à prendre en compte

  13. #13
    Nouveau Candidat au Club
    Femme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2012
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    UPDATE table_source  y SET y.exec ='D' WHERE y.ID = r.ID AND r.action ='ok'
    UPDATE table_source  y SET y.rej ='D' WHERE y.ID = r.ID AND r.action ='not ok'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IF r.action = 'ok' 
    THEN 
    	UPDATE table_source  y SET y.exec ='D' WHERE y.ID = r.ID
    ELSE
    	UPDATE table_source  y SET y.rej ='D' WHERE y.ID = r.ID
    END IF;
    Pouvez vous me dire comment traite ces deux cas les moteurs pl/sql et sql ?

    La version la plus performante est celle que vous n'avez pas exploitée, c'est à dire en FULL SQL.
    FULL SQL signifie à n'utiliser pas du tout pl/sql ?

    Merci beaucoup

  14. #14
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    Le moteur PL/SQL ouvre un curseur et pour chaque boucle envoi une instruction au moteur SQL pour mettre à jour la ligne correspondante.

    Quand je dis FULL SQL ça n'interdit pas le PL/SQL, c'est juste qu'au lieu de faire un curseur, une boucle une instruction de mise à jour, on fait une instruction SQL qui met à jour toutes les lignes.

  15. #15
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par McM Voir le message
    Sauf pour traiter les erreurs au niveau ligne. Imagine qu'il y a un trigger sur table_source qui peut sortir en erreur, un seul update ne serait pas gérable.
    Si, facilement, avec DML Error Logging.

    Le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ...
    exception when others then
    		UPDATE log SET obs ='err' WHERE id = r.id
    est le bug numéro 1 en Pl/SQL.

    Faire du DML en boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    For r In ... Loop
      Update ... set where r.id...
    End Loop;
    c’est le Pl/SQL de la grande mère !

  16. #16
    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
    1: DML Error Logging c'est à partir de la 10gR2
    2 : Le when others.. mouais.. .. moi je ne suis pas d'accord avec Tom Kyte.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  17. #17
    Nouveau Candidat au Club
    Femme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2012
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    Une clause where peut servir à filtrer des données lors de l'accès alors qu'une condition pl/sql va lire toutes les données pour les filtrer ensuite.
    Il sera toujours moins performant de faire un update qui va updater 0 ligne que de ne pas faire d'update !
    Le moteur PL/SQL ouvre un curseur et pour chaque boucle envoi une instruction au moteur SQL pour mettre à jour la ligne correspondante.

    Excusez moi pour l'insistance...
    Pouvez vous me dire comment traite ces deux cas les moteurs pl/sql et sql (l'instruction if-then-else ne charge plus le moteur pl/sql) ?

    Merci beaucoup

  18. #18
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par McM Voir le message
    ...2 : Le when others.. mouais.. .. moi je ne suis pas d'accord avec Tom Kyte.
    OK très bien chacun a ses gouts. Mais analysez l’exemple que j’ai extrait et dit moi vous ne trouvez pas qu’il y a un problème avec cette approche ?

  19. #19
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Chaque fois quand vous utilisez une construction similaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ...
    FOR r IN (SELECT * FROM log) loop
    begin
     
    IF r.date > trunc(sysdate-20) then 
    	UPDATE table_source  y SET y.exec ='D' WHERE y.id = r.id
    	UPDATE log SET obs ='exécuté' WHERE id = r.id
    c’est à dire un curseur qui cherche des valeurs pour alimenter par la suite une autre requête SQL vous devez vous poser des questions. En fait ce type de traitement est inefficace d’une part à cause des changements de contexte entre le moteur PL/SQL et le moteur SQL et d’autre part à cause du traitement ligne par ligne qu’il suppose.
    Deux solutions sont envisageables pour améliorer ce code :
    • Solution SQL : utilisez une seule requête SQL, dans votre cas un seul Update ou Merge
    • Solution PL/SQL : utilisez des collections c’est à dire traitement par lot et l’instruction FORALL…

  20. #20
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 21
    Points : 0
    Points
    0
    Par défaut
    oracle = machine à sql.

    donc il faut oublier le pl/sql, qui n'est qu'un pis-aller pour transférer un programme fortran des années 1970 vers oracle avec un taux de paresse maximum.

Discussions similaires

  1. Mauvaise performance avec Linq to sql
    Par Wasrack dans le forum Linq
    Réponses: 2
    Dernier message: 30/09/2009, 08h45
  2. Question sur les performance d'une transaction SQL
    Par SlashEne dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 24/04/2008, 22h41
  3. Performances temps d'insertions sql server
    Par KRis dans le forum Bases de données
    Réponses: 5
    Dernier message: 24/04/2008, 19h17
  4. Performance Hibernate vs PL-SQL.
    Par sqlbases dans le forum Hibernate
    Réponses: 4
    Dernier message: 22/05/2007, 10h00

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