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

Développement SQL Server Discussion :

Performance de la fonction SUBSTRING()


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Novembre 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant communication & réseaux

    Informations forums :
    Inscription : Novembre 2014
    Messages : 57
    Par défaut Performance de la fonction SUBSTRING()
    Bonjour à tous,

    Je rencontre un cas actuellement ou j'ai un SELECT dans une fonction qui prends environ 7 secondes par exécution. Le SELECT se fait sur 40000 lignes.

    La requete est la suivante:

    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
     
    ALTER FUNCTION [dbo].[SDD_PMTINFID] (@lot_id VARCHAR(20))
    RETURNS VARCHAR(35) AS
    BEGIN
     
      DECLARE @ret_ VARCHAR(35)='';
     
    -- Recuperation du compte concerne
    SELECT @ret_ = 
    				SUBSTRING(
    				CASE WHEN 
    						SUBSTRING(PAIEMENTX.USERZONE011,1,2) NOT IN ('T/','T|') THEN PAIEMENTX.USERZONE011 
    				WHEN 
    						(SUBSTRING(PAIEMENTX.USERZONE011,1,2) IN ('T/','T|')) AND (SUBSTRING(PAIEMENTX.USERZONE012,1,2) NOT IN ('T/','T|')) THEN PAIEMENTX.USERZONE012 
    				WHEN
    						(SUBSTRING(PAIEMENTX.USERZONE011,1,2) IN ('T/','T|')) AND (SUBSTRING(PAIEMENTX.USERZONE012,1,2) IN ('T/','T|')) THEN PAIEMENTX.USERZONE013 
    				END,
    				CHARINDEX('||',
    				CASE WHEN 
    						SUBSTRING(PAIEMENTX.USERZONE011,1,2) NOT IN ('T/','T|') THEN PAIEMENTX.USERZONE011 
    				WHEN 
    						(SUBSTRING(PAIEMENTX.USERZONE011,1,2) IN ('T/','T|')) AND (SUBSTRING(PAIEMENTX.USERZONE012,1,2) NOT IN ('T/','T|')) THEN PAIEMENTX.USERZONE012 
    				WHEN 
    						(SUBSTRING(PAIEMENTX.USERZONE011,1,2) IN ('T/','T|')) AND (SUBSTRING(PAIEMENTX.USERZONE012,1,2) IN ('T/','T|')) THEN PAIEMENTX.USERZONE013 
    				END)+2,16) + 
    				PAIEMENTX.PAIEMENTXLOTID 
    FROM PAIEMENTX 
    WHERE 
    	PAIEMENTX.PAIEMENTXLOTID = @lot_id;
      RETURN @ret_;	 
    END
    Est ce que, selon vous, l'utilisation de la fonction SUBSTRING() dans ma requete peut être à l'origine des problemes de perf que je rencontre ( car 7 s pour un select c'est un peu long je trouve ) .
    Le probleme est peut etre ailleurs je ne suis pas expert apres tout.

    Merci d'avance pour votre avis et éventuels conseils

    Bonne journée,

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Le problème de performance vient en général de l'accès aux données bien avant leur manipulation.

    Avez-vous un index / une partition sur la colonne PAIEMENTXLOTID ?

    Sinon, vos CASE peuvent être légèrement simplifiés, mais je doute que ça améliore significativement les performances :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    with cte_base (USERZONE) as
    (
    select case
             when substring(USERZONE011 from 1 for 2) not in ('T/','T|') then USERZONE011
             when substring(USERZONE012 from 1 for 2) not in ('T/','T|') then USERZONE012
                                                                         else USERZONE013
           end as USERZONE
      from PAIEMENTX
     where PAIEMENTXLOTID = @lot_id
    )
    select @ret_ = substring(USERZONE from charindex('||', USERZONE) + 2 for 16) + @lot_id
      from cte_base;

  3. #3
    Membre confirmé
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Novembre 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant communication & réseaux

    Informations forums :
    Inscription : Novembre 2014
    Messages : 57
    Par défaut
    Bonjour Waldar,

    Merci pour votre reponse.

    Citation Envoyé par Waldar Voir le message
    Avez-vous un index / une partition sur la colonne PAIEMENTXLOTID ?
    Oui j'ai bien un index sur la colonne PAIEMENTXLOTID. Je vais tester votre proposition d'optimisation et je vous dirai.

    Question subsidiaire si je peux : Est ce qu'il est judicieux de suivre les recommandations de SQL Server qui me préconise de faire de créer un index et de faire un INCLUDE ( nom de colonne, ... ).
    A quoi sert cet argument INCLUDE ? J'ai lu sur le sujet mais je ne suis pas sur d'avoir bien compris

    merci bcp!

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Oui ici ce serait très bien d'avoir l'index sur PAIEMENTXLOTID include (USERZONE011, USERZONE012, USERZONE013).

    Ça permet à SQL-Server de ne pas avoir besoin de lire la table puisque toutes les informations nécessaires sont présentes dans l'index.

  5. #5
    Membre confirmé
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Novembre 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant communication & réseaux

    Informations forums :
    Inscription : Novembre 2014
    Messages : 57
    Par défaut
    Bonjour,

    Merci pour vos reponses sur le INCLUDE. J'ai modifié l'index en conséquence:

    La requete

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    with cte_base (USERZONE) as
    (
    select case
             when substring(USERZONE011 from 1 for 2) not in ('T/','T|') then USERZONE011
             when substring(USERZONE012 from 1 for 2) not in ('T/','T|') then USERZONE012
                                                                         else USERZONE013
           end as USERZONE
      from PAIEMENTX
     where PAIEMENTXLOTID = @lot_id
    )
    select @ret_ = substring(USERZONE from charindex('||', USERZONE) + 2 for 16) + @lot_id
      from cte_base;
    me retourne le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Msg*156, Niveau*15, État*1, Ligne*4
    Incorrect syntax near the keyword 'for'.
    Msg*156, Niveau*15, État*1, Ligne*11
    Incorrect syntax near the keyword 'for'.
    Je bosse sur un serveur SQL Server 2014 ca peut expliquer?

    merci

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Je n'ai pas vérifié si SQL-Server supportait la syntaxe normative de SUBSTRING.
    Tant pis remplacez les from et for par des virgules (comme vous aviez fait).

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

Discussions similaires

  1. [Dates] "concaténation" de fonction substr et autres
    Par javaboy dans le forum Langage
    Réponses: 12
    Dernier message: 12/04/2007, 10h51
  2. Limite de la fonction substr
    Par zimotep dans le forum Langage
    Réponses: 2
    Dernier message: 31/10/2006, 01h45
  3. [XSL]appliquer la fonction substring sur une valeur récupéré
    Par totoranky dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 22/02/2006, 17h21
  4. Doublons et fonction substring-before
    Par dalefou dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 30/09/2005, 14h12
  5. Réponses: 5
    Dernier message: 13/07/2005, 10h03

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