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 :

MS SQL 2000 - Job SQL Agent beaucoup trop long


Sujet :

MS SQL Server

  1. #1
    Membre à l'essai
    Inscrit en
    Novembre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 6
    Par défaut MS SQL 2000 - Job SQL Agent beaucoup trop long
    Bonjour à vous tous. Je me tourne vers vous car après de longues recherches sur ce forum et sur le web je ne trouve pas de réponse à mon problème.

    J'ai un Job en Transact SQL que je dois faire tourner sur une base à peu prêt toutes les 2 / 3 minutes. Ce job fait des Update de champs tout simple.

    Mon job est trop long pour être directement implanté dans le SQL Agent j'ai donc créé une procédure stockée que j'appelle dans mon job.

    Mais voilà mon job met à peu prêt 2 minutes / 2minutes 40 à tourner (pour 4 update sur 14 lignes en tout) et fait monter en flèche le proc de mon serveur alors que quand je le tourne dans l'analyseur de requêtes, sur le même jeu d'enregistrement il s'exécute sans aucun problème en 2 secondes.

    L'utilisateur de mon Job est bien l'administrateur.

    Donc je pense ne pas utiliser l'Agent SQL de ce fait mais lancer en batch avec sqlcmd ma requete avec tache planifiée pour voir si ça tourne mieux.

    Sinon si vous savez pourquoi l'agent SQL est si lent et si gourmand je suis preneur.

    Pour info voici mon Job, je travaille sur une BDD de SAGE Ligne 100 SQL. Je traite le verrouillage des lignes.

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    SET NOCOUNT ON
    DECLARE @DO_PIECE varchar(9)
    DECLARE @DO_TYPE smallint
    DECLARE @DO_DOMAINE smallint
    DECLARE @DO_cbMarq int
    DECLARE @DO_Dure_Contrat numeric
    DECLARE @DO_majorachat numeric
    DECLARE @lock int
     
    set @DO_DOMAINE = 0 -- 0=ventes
    set @DO_TYPE = 0 -- 0=devis
     
    -- Table temporaire de jointure entre les do_cbmarq et les dl_cbmarq :
    select do.cbMarq DOcbMarq, dl.cbMarq DLcbMarq
    into #temp
    from F_DOCENTETE do
    inner join F_DOCLIGNE dl on do.DO_Domaine = dl.DO_Domaine
    	and do.DO_Type = dl.DO_Type and do.DO_Piece = dl.DO_Piece
    WHERE do.crmsync='linesnotok' and do.DO_Ref = 'QT-298/4'
    and do.DO_Domaine = @DO_DOMAINE and do.DO_Type = @DO_TYPE
    and isnull(dl.AR_Ref,'') <> ''
     
    if((select count(*) from #temp) > 0)
    BEGIN
     
    	-- Connexion à la Gescom :
    	exec CB_Connect 'CIAL'
     
    	DECLARE MyCursor CURSOR FOR
    	 SELECT do.DO_PIECE,do.cbMarq,do.Dure_Contrat,isnull(do.majorachat,0) majorachat FROM F_DOCENTETE do
    	 inner join (select distinct DOcbMarq from #temp) tmp on do.cbMarq = tmp.DOcbMarq
    	 ORDER BY do.cbMarq
     
    	OPEN MyCursor -- j'initialise mon curseur 
     
    	-- je le rempli avec la première ligne retournée par la requête 
    	FETCH NEXT FROM MyCursor INTO @DO_PIECE, @DO_cbMarq, @DO_Dure_Contrat, @DO_majorachat 
     
    	-- Tant que je n'ai pas traité tous les enregistrements de le requête 
    	WHILE @@FETCH_STATUS  = 0 
    	BEGIN 
    		exec CB_IsRecordLock 'F_DOCENTETE', @DO_cbMarq, @lock OUTPUT --Test si l'enregistrement est locké
    		-- Ne pas lever d'erreur afin de pouvoir continuer le traitement sur les autres documents éventuels :
    		IF @lock = 0
    		BEGIN
     
    		  -- Verrouillage du document :
    		  exec CB_LockRecord 'F_DOCENTETE', 3, @DO_cbMarq
     
    		  if(@DO_majorachat<>0)
    		  BEGIN
    			--  1- Majoration des Lignes de Rachat
    			UPDATE dl 
    			SET dl.DL_QteBC = dl.DL_Qte*1.1,
    			dl.DL_QteBL = dl.DL_Qte*1.1,
    			dl.EU_Qte = dl.DL_Qte*1.1, 
    			dl.DL_MontantHT = dl.DL_Qte*1.1, 
    			dl.DL_MontantTTC = ROUND(dl.DL_Qte*1.1*(1+(dl.DL_Taxe1/100)),2), 
    			dl.DL_Qte = dl.DL_Qte*1.1
    			FROM F_DOCLIGNE dl
    			INNER JOIN #temp tmp on dl.cbMarq = tmp.DLcbMarq
    			WHERE tmp.DOcbMarq = @DO_cbMarq
    			AND dl.AR_Ref = 'RACHVIDCST'
     
    			--  2- Majoration Remise
    			UPDATE dl 
    			SET dl.DL_MontantHT = dl.DL_MontantHT-@DO_majorachat, 
    			dl.DL_MontantTTC = dl.DL_MontantTTC-ROUND(@DO_majorachat*(1+(dl.DL_Taxe1/100)),2) 
    			FROM F_DOCLIGNE dl
    			INNER JOIN #temp tmp on dl.cbMarq = tmp.DLcbMarq
    			WHERE tmp.DOcbMarq = @DO_cbMarq
    			AND dl.AR_Ref = 'REM_VI'
    		  END
     
    		  --  3- Valorisation Loyer
    		  UPDATE dl 
    		  SET dl.DL_PoidsBrut = ROUND(((dl.DL_MontantHT/(@DO_Dure_Contrat/1.2))*1000),2) 
    		  FROM F_DOCLIGNE dl
    		  INNER JOIN #temp tmp on dl.cbMarq = tmp.DLcbMarq
    		  WHERE tmp.DOcbMarq = @DO_cbMarq
     
    		  -- 4 ReFlag de l'entête
    		  UPDATE F_DOCENTETE 
    		  SET crmsync='linesok', majorachat = 0
    		  WHERE F_DOCENTETE.cbMarq = @DO_cbMarq
     
    		  -- Déverrouillage du document :
    		  exec CB_UnLockRecord 'F_DOCENTETE', 3, @DO_cbMarq
     
    		END
    		FETCH NEXT FROM MyCursor INTO @DO_PIECE, @DO_cbMarq, @DO_Dure_Contrat, @DO_majorachat 
    	END 
     
    	CLOSE myCursor -- je ferme mon curseur 
    	DEALLOCATE myCursor -- je libère la mémoire allouée à ce curseur
     
    	-- Déconnexion de la Gescom :
    	exec CB_Disconnect
    END
     
    -- Suppression de la table temporaire :
    drop table #temp
    Merci à tous ceux qui auront la gentillesse de m'aider !

    Bonne journée.

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 994
    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 994
    Billets dans le blog
    6
    Par défaut
    1) vous n'avez pas préfixé les objets (tables, vues, procédures....) par leur schéma. Même si vous n'utilisez qu'un seul schéma de nom dbo, il est extrêmement important pour les performances, que ce préfixe soit mis partout !
    2) vous pourriez supprimer votre curseur et le remplacer par une vue ou une CTE. Tout traitement à base de curseur est strictement inoptimisable !
    3) l'utilisation des tables temporaires est contre performantes car impose des opérations de transactions donc d'écriture physique dans le fichier du journal de transaction. Supprimez votre table temporaire, remplacez la par une vue ou une CTE
    4) le verrouillage pessimiste est la pire des choses qui à conduit les bases de données de type "fichier" à la mort, et c'est la raison pour laquelle dans les bases de données de type C/S transactionnelle il a été abandonné au profit des transactions.
    5) vous enchainez 3 UPDATE sur la même table dans la boucle alors qu'un seul update suffit en utilisant un CASE.

    Bref ce code épouvantable semble avoir été écrit par une personne n'ayant strictement aucune connaissance de ce qu'est un SGBDR C/S transactionnelle et à reproduit un schéma fonctionnel propre aux fichiers COBOL !
    Ne vous étonnez donc pas des lenteurs épouvantables que cela engendre car visiblement le SGBDR est utilisé à contre emploi !

    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/ * * * * *

  3. #3
    Membre à l'essai
    Inscrit en
    Novembre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 6
    Par défaut
    1- Je cherche pour prefixer par le schéma car je ne sais pas ce qu'est le schéma?
    http://blog.developpez.com/sqlpro/p5...es-schema-sql/

    2/4- Pour ce qui est du verrouillage je pense que je n'ai pas le choix SAGE L100 les gère de cette façon. Je suis obligé de tester et verrouiller de cette manière pour que l'appli n'interfère pas sur les enregistrements que je traite. Ce qui me force à utiliser un curseur pour tester ligne par ligne !?
    Effectivement, mais c'est vraiment pas bon pour les perfs....

    3- La table temporaire a été mise en place par une personne ayant l'habitude de gérer les bases lignes 100 je vais voir comment faire autrement.
    Passez par une vue car vous ne pouvez pas faire de CTE sous 2000.

    Pensez cependant à migrer sous 2008 car la version 2000 ne sera bientôt plus supportée. Cela peut signifier un écart à terme trop important entre les version (donc migration directe impossible) voir pire une incompatibilité d'OS entre la version 2000 et le futur Windows server....

    5- Je vais modifier les update avec un case
    C'est pas trop difficile !

    A +


    Merci pour votre aide.

  4. #4
    Membre à l'essai
    Inscrit en
    Novembre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 6
    Par défaut
    Merci pour cette dernière réponse qui m'aide grandement.

    C'est pas trop difficile !
    ... quand on en a déjà fait !

    Merci encore!

  5. #5
    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 : 43
    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
    Par défaut
    Bonjour,

    Je pense que votre première requête peut s'écrire comme suit :

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    UPDATE dbo.F_DOCLIGNE
    SET dl.DL_QteBC = CASE dl.AR_Ref
    					WHEN 'RACHVIDCST' THEN CASE
    												WHEN TMP.majorachat <> 0 THEN dl.DL_Qte * 1.1
    												ELSE dl.DL_QteBC
    											END
    				END,
    	dl.DL_QteBL = CASE dl.AR_Ref
    					WHEN 'RACHVIDCST' THEN CASE
    												WHEN TMP.majorachat <> 0 THEN dl.DL_Qte * 1.1
    												ELSE dl.DL_QteBL
    											END
    				END,
    	dl.EU_Qte = CASE dl.AR_Ref
    					WHEN 'RACHVIDCST' THEN CASE
    												WHEN TMP.majorachat <> 0 THEN dl.DL_Qte * 1.1
    												ELSE dl.EU_Qte
    											END
    				END,
    	dl.DL_MontantHT = CASE dl.AR_Ref
    							WHEN 'RACHVIDCST' THEN CASE
    														WHEN TMP.majorachat <> 0 THEN dl.DL_Qte * 1.1
    														ELSE dl.DL_MontantHT
    													END
    							WHEN 'REM_VI' THEN dl.DL_MontantHT - TMP.majorachat
    							ELSE dl.DL_MontantHT
    						END,
    	dl.DL_MontantTTC = CASE dl.AR_Ref
    							WHEN 'RACHVIDCST' THEN CASE
    														WHEN TMP._majorachat <> 0 THEN ROUND(dl.DL_Qte * 1.1 * (1 + (dl.DL_Taxe1 / 100)), 2)
    														ELSE dl.DL_MontantTTC
    													END
    							WHEN 'REM_VI' THEN dl.DL_MontantTTC - ROUND(TMP.majorachat * (1 + (dl.DL_Taxe1 / 100)), 2) 
    							ELSE dl.DL_MontantTTC
    						END,
    	dl.DL_Qte = CASE dl.AR_Ref
    							WHEN 'RACHVIDCST' THEN CASE
    														WHEN @DO_majorachat <> 0 THEN dl.DL_Qte * 1.1
    														ELSE dl.DL_Qte
    													END
    				END,
    	dl.DL_PoidsBrut = ROUND(((dl.DL_MontantHT / (@DO_Dure_Contrat/1.2)) * 1000), 2),
    FROM dbo.F_DOCLIGNE AS DL
    INNER JOIN
    (
    	SELECT do.cbMarq DOcbMarq,
    			dl.cbMarq DLcbMarq,
    			do.DO_PIECE,
    			do.cbMarq,
    			do.Dure_Contrat,
    			ISNULL(do.majorachat, 0) majorachat
    	FROM dbo.F_DOCENTETE AS do
    	INNER JOIN dbo.F_DOCLIGNE AS dl
    		ON do.DO_Domaine = dl.DO_Domaine
    		AND do.DO_Type = dl.DO_Type
    		AND do.DO_Piece = dl.DO_Piece
    	WHERE do.crmsync='linesnotok'
    	AND do.DO_Ref = 'QT-298/4'
    	AND do.DO_Domaine = @DO_DOMAINE
    	AND do.DO_Type = @DO_TYPE
    	AND ISNULL(dl.AR_Ref,'') <> ''
    ) AS TMP (DOcbMarq, DLcbMarq, DO_PIECE, cbMarq, Dure_Contrat)
    	ON DL.cbMarq = TMP.DLcbMarq
    	AND DO.cbMarq = TMP.DOcbMarq
    Voyez ici pourquoi le fait de ne pas qualifier vos tables avec le nom du schéma est contre-performant : cela oblige SQL Server à rechercher dans les tables de métadonnées le propriétaire de la table et ensuite de le comparer avec l'utilisateur qui exécute la procédure.
    Le schéma par défaut est dbo

    Je montre ici que les curseurs sont contre-performants : vous obligez SQL Server à traiter l'ensemble des données de votre curseur ligne à ligne comme on le fait avec un langage procédural, de façon itérative.
    Or SQL est conçu pour manipuler des ensembles de données, et s'avère être donc très mauvais sur les itérations.

    Je montre ici pourquoi l'utilisation de tables temporaires ou de variables de type TABLE est une mauvaise pratique.

    Que ce soit pour les curseurs ou les tables temporaraires, leur utilisation montre soit une méconnaissance du langage SQL (et T-SQL), soit une mauvaise qualité du modèle de données. Dans le pire des cas, les deux ...

    L'opérateur CASE, comme vous le verrez dans la requête que je vous propose, permet de valeur une colonne suivant un prédicat.

    Enfin les expressions de table commune ayant été introduites avec SQL Server 2005, elles n'étaient pas encore implémentées dans SQL Server 2000, mais vous pouvez contourner cela soit avec une table virtuelle, soit comme vous l'a proposé williamc73 avec une vue.

    @++

  6. #6
    Membre à l'essai
    Inscrit en
    Novembre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 6
    Par défaut
    Bonjour Elsuket et merci grandement c'est tout simplement génial je vais pouvoir analyser vos explications et en savoir plus sur les optimisations de requete en sachant pourquoi il ne faut pas faire ceci ou cela ! GENIAL.

    Par contre, je travaille sur la base de Donnée SAGE Ligne 100 SQL... Utilisée par l'application SAGE Gestion Commerciale.
    Cette application verrouille les enregistrements utilisés avec des procédures prévues à cet effet je ne peux donc absolument pas mettre à jour un ensemble de donnée d'un coup mais je dois hélas tester chaque enregistrement pour savoir s'il est verrouillé avant de l'updater et donc à mon grand regret utiliser un curseur sinon la requete de traitement d'ensemble est plantée !

    Merci beaucoup encore une fois pour votre intervention !

  7. #7
    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 : 43
    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
    Par défaut
    Je ne connais pas du tout SAGE Ligne 100 SQL, mais je me doute que vous avez posté ici parce que vous savez que ce logiciel utilise une base de donnée SQL Server.

    Si SAGE Ligne 100 SQL implémente un verrouillage pessimiste, alors ce n'est pas un produit que je conseillerai si je distribuais des logiciels de CRM.

    SQL Server sait très bien gérer les transactions et le verrouillage tout seul, et j'aimerai bien avoir une explication de la part de SAGE sur cette implémentation qui me paraît médiocre ... pour rester poli

    Cela explique néanmoins (et malheureusement) l'utilisation du curseur.

    @++

  8. #8
    Membre à l'essai
    Inscrit en
    Novembre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 6
    Par défaut
    SAGE Ligne 100 est à l'origine créé avec une base de donnée CBASE... je crois que c'est plus tard qu'ils ont fournis une version sur SQL Server. Ils ont du faire certaines choses en fonction de cela ? Mais en effet le verrouillage me pose bien des problèmes.

    J'ai donc repris votre requete et l'ai implanté avec le curseur, modifié la requete car elle mettait a blanc mes quantités dans le cas où AR_Ref n'était pas égal à 'RACHVIDCST' ou 'REMVI' , supprimé la table temporaire et créé une vue la remplaçant. Pour terminer j'ai prefixé tout ce qui pouvait être prefixé par dbo.

    J'ai fait mes premiers tests dans l'analyseur de requêtes et une fois sur les 5 fois où j'ai exécuté ma requete j'ai reçu le message d'erreur suivant :
    "La transaction (ID du processus 219) a été bloquée sur les ressources lock | communication buffer par un autre processus et a été choisie comme victime. Relancez la transaction."

    Je vais voir dans le SQL Agent maitenant que ma requete est juste mais je crains que le SQL Agent n'aime toujours pas... surement à cause du curseur et des verrouillages.

    Merci pour votre aide en tout cas et toutes ces infos qui vont m'aider à progresser en optimisation SQL.

  9. #9
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 994
    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 994
    Billets dans le blog
    6
    Par défaut
    Pour mémoire, effectivement cette ligne 100 vient à l'origine d'une système de fichier plat et non d'une base relationnelle. L'adaptation à SQL Server est malheureuse !

    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/ * * * * *

  10. #10
    Membre à l'essai
    Inscrit en
    Novembre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 6
    Par défaut
    Bonjour SQLPro je suis d'accord avec vous pour ce qui est de la ligne 100 le portage SQL Serveur n'a pas l'air des mieux !


    En ce qui concerne mes tests :

    Je viens de tester dans le SQL Agent 1minute30 d'exécution, mais c'est sans utilisateur entre midi et deux , c'est moins lourd qu'hier certes, mais je pense qu'avec des utilisteurs ça va planter à mon avis il y a des interérences avec d'autres process de la ligne 100 que je ne maîtrise pas.

    En batch avec osql.exe ... c moins long, ça passe, mais j'ai autant de doute qu'avec le SQL Agent... bref je ne m'en sors pas !

    Par contre avec l'analyseur de requêtes 2 secondes d'exécution nickel...


    @+

Discussions similaires

  1. Migration Sql 2000 vers sql 2008
    Par Palenf dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 06/05/2010, 21h09
  2. Migration SQL 2000 vers SQL 2005 Express
    Par jubourbon dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 07/04/2009, 08h20
  3. Environement mixte SQL 2000 et sql 2005
    Par didier.M dans le forum Administration
    Réponses: 0
    Dernier message: 31/07/2008, 15h08
  4. Transfert base sql 2000 vers SQL 2005
    Par franck SEFIC dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 29/02/2008, 15h22
  5. Cohabitation SQL 2000 et SQL 2005
    Par DOMINO53 dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 17/12/2007, 14h56

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