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

MS SQL Server Discussion :

Requete qui n'aboutit pas


Sujet :

MS SQL Server

  1. #1
    Membre confirmé Avatar de juvamine
    Profil pro
    Chef de projet MOA
    Inscrit en
    Mai 2004
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2004
    Messages : 414
    Points : 502
    Points
    502
    Par défaut Requete qui n'aboutit pas
    ou plutot... qui n'aboutit plus !

    Bonjour à tous,

    Je remarque un comportement étrange chez l'un de nos clients, et je ne parviens pas à le régler, ni même à l'expliquer.

    Un jour il nous appelle pour nous signaler des blocages de l'appli. Après vérif du serveur, il y avait un nombre impressionants de verrou sur la base. Bref, j'identifie le verrou "source", le kill et tout repart comme en 14.
    J'ai tout de même prit le soin de récupérer la requête. Sans surprise, lorsque je l'exécute dans ssms, je reverrouille tout le monde...

    La requête en question, faisait appel à une fonction table...j'explore la fonction qui n'a rien de bien méchant...mais soit ! Je fais une modif et transforme la fonction table, en fonction inline (ce qui m'oblige de faire un drop function avant)

    Et hop ça roule...
    Afin de retravailler ma fonction correctement je remets la fonction initiale ==> et ça fonctionne également

    Nous sommes donc revenu à la fonction de départ, et tout fonctionne (le DROP, CREATE a donc un impact)
    Je confirme cette "solution" lorsqu'il me rappelle 2 mois plus tard pour le même problème, je DROP, et CREATE la fonction table : et c'est reparti.

    Il doit donc y avoir un fonctionnement de SQLServer (stockage d'info, de stats, ou je ne sais quoi), qui est réinitialisé quand on DROP un objet.

    J'ai essayé de reproduire les objet de manière plus simple pour expliquer :

    La fonction ressemble à cela :
    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
    Create function Fonction_Table_1(@Param1 int)
    Returns @Tab Table(Champ_retour1 int)
    AS
    BEGIN
    	if @Param1 = 1
    		insert @Tab(Champ1)
    		SELECT A
    		FROM Table1
    		WHERE [Conditions]
     
    	else if @Param1 = 2
    		insert @Tab(Champ1)
    		SELECT A
    		FROM Table1
    		WHERE [Autres_Conditions]
     
    	else if @Param1 = 3
    		insert @Tab(Champ1)
    		SELECT A
    		FROM Table1 t1
    		WHERE [Autres_Conditions] 
    		AND NOT EXISTS(SELECT 1 FROM Table2 t2 WHERE t2.champ1 = t1.champ12)
    END
    La requete qui créé les verrous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    INSERT INTO Table_Temp(Champ1, Champ2, Champ3, Champ4)
    SELECT distinct 2, 1500, Champ_retour1, 0
    FROM Table1 t1 
    INNER JOIN Fonction_Table_1 ft1 ON ft1.Champ_retour1 = t1.A
    AND  [conditions_diverses]
    => Le simple fait de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select Champ_retour1 FROM Fonctoin_Table_1(3)
    génère un problème identique.... Preuve que le soucis vient bien de la fonction table.

    Pouvez-vous m'expliquer quel phénomène pourrait expliquer ce comportement ?
    Et accessoirement, comment le régler ?

    Pour info :
    un CHECKDB et une réindexation complète de la base de données est effectué chaque jour sur la base
    nous sommes en mode de récupération "complète"
    SqlServer ne met pas forcément le serveur "à genoux" à ce moment là
    La tempdb grossit assez peu chez ce client (mais j'ai l'impression que le problème ce situerais dans cette dernière ?)

    Je reste à votre dispo si vous manquez d'info.
    S'il le faut je mettrai le cas réel...

    Merci d'avance pour votre aide
    Amicalement,
    Juvamine
    Juvamine

  2. #2
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Je ne vois pas l'appel à la fonction dans la 1ère requête "qui bloque" ?

    Sinon, pourquoi ne pas faire une bête vue ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    CREATE VIEW v_Fonction_Table_1 AS
    SELECT 1 AS param, A
      FROM Table1
    WHERE [Conditions]
    UNION ALL
    SELECT 2 AS param, A
       FROM Table1
     WHERE [Autres_Conditions]
    UNION ALL 
    SELECT 3 AS param, A
      FROM Table1 t1
     WHERE [Autres_Conditions] 
         AND NOT EXISTS(SELECT 1 FROM Table2 t2 WHERE t2.champ1 = t1.champ12)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT Champ_retour1 FROM v_Fonction_Table_1 
    WHERE param = 3

  3. #3
    Membre confirmé Avatar de juvamine
    Profil pro
    Chef de projet MOA
    Inscrit en
    Mai 2004
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2004
    Messages : 414
    Points : 502
    Points
    502
    Par défaut
    Citation Envoyé par Rei Ichido Voir le message
    Je ne vois pas l'appel à la fonction dans la 1ère requête "qui bloque" ?
    Corrigé, désolé ^^


    Citation Envoyé par Rei Ichido Voir le message

    Sinon, pourquoi ne pas faire une bête vue ?
    Sur le principe je suis pas contre, mais ne sachant pas ce qui créé le blocage avec une simple fonction table, je ne peux pas dire que je n'aurai par le problème avec la vue !
    Je cherche surtout à comprendre car peut être que notre appli est truffée de chose de ce genre, qui sont finalement des bombes a retardement que l'on arrive a désamorcer de manière "temporaire".
    Juvamine

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Ce peut être effectivement dû aux statistiques, et il aurait fallu pour le savoir capturer le plan d'exécution et regarder l'estimation de cardinalités par rapport au nombre de lignes réel retourné.

    Ce que vous faites en supprimant puis recréant la fonction aboutit à une recompilation de la procédure stockée, ce qui indique très probablement un problème avec les statistiques de colonne. Mais c'est difficile à dire sans le plan d'exécution.

    Notez cependant que les fonctions n'ont :

    - pas de comportement ensembliste comme l'est SQL, et elles peuvent donc pénaliser les performances
    - pas de statistiques : elles empêchent SQL Server d'effectuer une estimation de cardinalités correcte. Il devine donc la cardinalité.

    Notons d'ailleurs les fonctions n'apparaissent pas dans les plans d'exécution.

    En revanche la solution que propose Rei Ichido est probablement la bonne : avec les vues, SQL Server peut effectuer une estimation de cardinalités correcte.

    Est-ce que vous maintenez les statistiques sur la base de données en question ?

    @++

  5. #5
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Je pense (et suis étonné que ce ne fut pas mentionné) que vous avez un problème de Parameter sniffing.

    Dans votre fonction, essayez l'option WITH RECOMPILE pour chacun de vos insert.
    Most Valued Pas mvp

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 848
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 848
    Points : 52 966
    Points
    52 966
    Billets dans le blog
    6
    Par défaut
    1) les cardinalités des fonctions tables, particulièrement table multi instruction, sont systématiquement évaluées à 1. En effet il n'est pas possible de disposer de statistiques de données sur des données qui... n'existent pas ! En effet, les données d'une fonction ne sont connues qu'une fois le code exécuté, c'est à dire bien après l'estimation du plan. Bref, l'utilisation de telles UDF conduit systématiquement à des plans faux...
    2) une amélioration consiste effectivement à choisir de préférence une table INLINE plutôt que multi instructions
    3) effectivement l'option WITH RECOMPILE est souvent payante dans ce cas, car cela évite la reprise d'un plan déjà faux.
    4) tout ce qui est code itératif est inoptimisable. Il suffit alors de supprimer ce code et de le remplacer par du code ensembliste, c'est à dire par une requête.

    Dans la 4e édition de mon bouquin sur SQL à paraître début juillet, je montre quelques exemples tragique de ce cas ou le plan semble être efficace et ou il s'avère particulièrement catastrophique !

    Supprimez cette fonction et remplacer tout ceci par un CASE dans la requête finale.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Membre confirmé Avatar de juvamine
    Profil pro
    Chef de projet MOA
    Inscrit en
    Mai 2004
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2004
    Messages : 414
    Points : 502
    Points
    502
    Par défaut
    Bonjour,
    Désolé d'avoir mis un peu de temps à répondre et merci.

    Bon déjà il est difficile de modifier la requete source. Elle est dynamique et du coup ce serait une refonte complète d'un module (module de requetage d'ailleurs)
    Mais il sera assez simple de la modifier pour la passer en inline, et du coup je pourrais ajouter le with recompile.

    bon maintenant : dois-je systématiquement utiliser le with recompile ?
    Ou est-ce qu'il y a un contexte particulier à respecter.

    Merci d'avance pour vos réponse et pour votre aide déjà fournie.

    A bientot
    Juvamine

Discussions similaires

  1. Requete qui ne renvoie pas de résultat
    Par bruno782 dans le forum Requêtes
    Réponses: 6
    Dernier message: 01/08/2019, 13h39
  2. Comment diagnostiquer une requete qui n'aboutit pas?
    Par Sunsawe dans le forum Réseau
    Réponses: 1
    Dernier message: 21/12/2010, 08h53
  3. [ASE][T-SQL] Requete qui n'aboutit pas
    Par metheorn dans le forum Sybase
    Réponses: 4
    Dernier message: 06/07/2006, 11h56
  4. Requete qui ne fonctionne pas chez l'hebergeur
    Par Derik dans le forum Requêtes
    Réponses: 4
    Dernier message: 05/06/2006, 02h35
  5. [PL/SQL] requete qui marche mais pas dans un cursor
    Par victor.ward dans le forum Langage SQL
    Réponses: 3
    Dernier message: 09/09/2005, 22h21

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