Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server
MS SQL-Server Forum Microsoft SQL-Server. Avant de poster -> FAQ SQL-Server, Tutoriels SQL-Server
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 19/12/2011, 15h24   #1
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 670
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

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

Informations forums :
Inscription : janvier 2005
Messages : 4 670
Points : 8 732
Points : 8 732
Par défaut Problème de résultat avec une vue indexée

Bonjour,

Voici donc la requête que je cherche à optimiser :

Code :
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
SELECT		DISTINCT TOP 10 TI.ti_id
		, T.task_id
		, T.batch_size
		, TI.ti_rowversion
		, T.task_autorelease
		, T.task_timeout
		, T.task_base_url
		, TM.training_method_icon
		, TR.training_content_url
		, TI.ti_priority
		, 2 AS status_code
FROM		dbo.team_task_instance AS TI
INNER JOIN	dbo.team_task AS T
			ON TI.task_id = T.task_id
			AND T.rec_status = 1
INNER JOIN	dbo.auth_user_in_role AS r
			 ON
			 (
				(
					TI.role_Id IS NOT NULL
					AND r.roleid = TI.role_id
				)
				OR
				(
					TI.role_Id IS NULL
					AND r.roleid = T.role_id
				)
			)
			AND r.userid = @user_id
			AND r.rec_status = 1
INNER JOIN	dbo.team_task_user_preference AS tup
			ON tup.task_id = T.task_id
			AND tup.[user_id] = @user_id
			AND tup.rec_status = 1
LEFT JOIN	dbo.team_training_resource AS TR
			ON  T.task_id = TR.task_id
			AND TR.language_id = @language_id
			AND TR.rec_status = 1
LEFT JOIN	dbo.team_training_method AS TM
			ON TR.training_method_id = TM.training_method_id
			AND TM.rec_status = 1
WHERE		TI.rec_status = 1
AND		TI.completed_when IS NULL
AND		TI.ti_locked_by IS NULL
AND		TI.ti_person IS NULL
AND		(
			TI.skill_code = r.skill_code
			OR TI.skill_code IS NULL
		)
ORDER BY	TI.ti_priority DESC
J'ai donc créé une vue indexée (le code dans quelques lignes), et j'ai changé l'horrible OR de la jointure en UNION.
Tout se passait bien, jusqu'à que je teste avec différentes valeurs de @user_id.
Si j'exécute la requête ci-dessus, j'ai un résultat, et si j'exécute la requête en référençant la vue indexée, j'ai très exactement le même jeu de données, sauf que la colonne ti_id de mon résultat contient des valeurs tout à fait différentes.

Au départ j'ai cru que j'avais fait une erreur dans l'UNION, et c'est pour cela que je suis revenu à la requête avec OR, pour être sûr d'avoir le résultat attendu.

Donc voici la vue indexée :

Code :
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
CREATE VIEW dbo.team_task_claim
	WITH SCHEMABINDING
AS
	SELECT		TI.ti_id
			, T.task_id
			, T.batch_size
			, TI.ti_rowversion
			, T.task_autorelease
			, T.task_timeout
			, T.task_base_url
			, TI.ti_priority
			, TI.ti_locked_by
			, TI.ti_person
			, COALESCE(TI.role_id, T.role_id) AS role_id
			, TI.skill_code
	FROM		dbo.team_task_instance AS TI
	INNER JOIN	dbo.team_task AS T
				ON TI.task_id = T.task_id
	WHERE		T.rec_status = 1
	AND		TI.rec_status = 1
	AND		TI.completed_when IS NULL
GO
 
CREATE UNIQUE CLUSTERED INDEX IXUQ_team_task_claim__ti_id__task_id
ON dbo.team_task_claim (ti_id, task_id)
GO
Et voici la requête qui utilise cette vue :

Code :
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
SELECT		DISTINCT TOP 10 T.ti_id
		, T.task_id
		, T.batch_size
		, T.ti_rowversion
		, T.task_autorelease
		, T.task_timeout
		, T.task_base_url
		, TM.training_method_icon
		, TR.training_content_url
		, T.ti_priority
		, 2 AS status_code
FROM		dbo.team_task_claim AS T WITH (NOEXPAND)
INNER JOIN	dbo.auth_user_in_role AS r
			 ON
			 (
				(
					T.task_instance_role_Id IS NOT NULL
					AND r.roleid = T.task_instance_role_Id
				)
				OR
				(
					T.task_instance_role_Id IS NULL
					AND r.roleid = T.task_role_id
				)
			)
			AND r.userid = @user_id
			AND r.rec_status = 1
INNER JOIN	dbo.team_task_user_preference AS tup
			ON tup.task_id = T.task_id
			AND tup.[user_id] = @user_id
			AND tup.rec_status = 1
LEFT JOIN	dbo.team_training_resource AS TR
			ON  T.task_id = TR.task_id
			AND TR.language_id = @language_id
			AND TR.rec_status = 1
LEFT JOIN	dbo.team_training_method AS TM
			ON TR.training_method_id = TM.training_method_id
			AND TM.rec_status = 1
WHERE		T.ti_locked_by IS NULL
AND		T.ti_person IS NULL
AND		(
			T.skill_code = r.skill_code
			OR T.skill_code IS NULL
		)
ORDER BY T.ti_priority DESC
Le pire, c'est que quand j'enlève l'indicateur NOEXPAND, j'ai un résultat identique à la requête originale, mais sans les performances

Je précise que le but premier de cette discussion n'est pas l'optimisation, mais seulement de comprendre pourquoi je n'obtiens pas strictement le même résultat.
J'ai du faire une boulette mais je ne la vois pas

Pour vous donner une idée, la taille de la table dbo.team_task est de 17 lignes, et sa copine dbo.team_task_instance est de quelques dizaines de millions.

J'ai essayé de tuner la requête avec des index sur les tables, mais je n'obtiens pas le gain de performance phénoménal et nécessaire au business : la procédure stockée doit s'exécuter en au plus 15ms, et la vue indexée est utilisée par 4 autres requêtes dans cette même procédure stockée.
Cela fonctionne très bien avec la vue indexée (je suis passé sous les 10ms), mais je n'ai pas le bon résultat

Je suis ouvert à toute proposition, y compris le remplacement de la vue indexée.

Merci de votre aide

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/12/2011, 22h59   #2
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 959
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 959
Points : 17 791
Points : 17 791
AMHA : top 10 !

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 11h14   #3
Membre Expert
 
Homme Etienne ZINZINDOHOUE
Ingénieur développement
Inscription : mars 2010
Messages : 1 139
Détails du profil
Informations personnelles :
Nom : Homme Etienne ZINZINDOHOUE
Localisation : France, Nord (Nord Pas de Calais)

Informations professionnelles :
Activité : Ingénieur développement
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : mars 2010
Messages : 1 139
Points : 2 470
Points : 2 470
Envoyer un message via Yahoo à zinzineti
difficile de faire du tunning sans jeu de données
__________________
Etienne ZINZINDOHOUE
Billets-Articles
zinzineti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 11h51   #4
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 670
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

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

Informations forums :
Inscription : janvier 2005
Messages : 4 670
Points : 8 732
Points : 8 732
Ce que je ne comprend pas c'est qu'en exécutant la requête deux fois sur une copie de la base de données où je suis sûr d'être le seul à travailler, j'ai des résultat différents à chaque exécution ...

Je comprend que le TOP soit en cause, mais si le résultat change à chaque exécution, là y'a un problème ...

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 11h57   #5
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 670
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

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

Informations forums :
Inscription : janvier 2005
Messages : 4 670
Points : 8 732
Points : 8 732
Je viens de trouver qu'en empêchant SQL Server d'utiliser la parallélisation à l'aide de l'indicateur de requête OPTION (MAXDOP 1), j'ai des résultats identiques de façon consistante.

Avez-vous rencontré des problèmes similaires ?

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 12h18   #6
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 959
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 959
Points : 17 791
Points : 17 791
C'est lié au TOP !!! En fait avec un seul thread possible il prend toujours les données de la même façon. Avec plusieurs thread il te rend les premières lignes d'un des thread...

Le TOP a toujours été inconsistant !!!!! Parce que pas relationnel...

essaye avec RANK

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 12h37   #7
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 670
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

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

Informations forums :
Inscription : janvier 2005
Messages : 4 670
Points : 8 732
Points : 8 732
Citation:
Le TOP a toujours été inconsistant !!!!! Parce que pas relationnel...
héhé je sais bien, mais il est des cas où malheureusement on en a besoin, surtout quand cela dépend du temps ... pas cool le TOP

Je viens d'essayer avec ceci :

Code :
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
SELECT	TOP 10 *
FROM	(
		SELECT		DISTINCT T.ti_id
				, T.task_id
				, T.batch_size
				, T.ti_rowversion
				, T.task_autorelease
				, T.task_timeout
				, T.task_base_url
				, TM.training_method_icon
				, TR.training_content_url
				, T.ti_priority
				, 2 AS status_code
				, ROW_NUMBER() OVER(ORDER BY T.ti_priority DESC) AS n
		FROM		dbo.team_task_claim_2 AS T WITH (NOEXPAND)
		INNER JOIN	dbo.auth_user_in_role AS r
					 ON
					 (
						(
							T.task_instance_role_Id IS NOT NULL
							AND r.roleid = T.task_instance_role_Id
						)
						OR
						(
							T.task_instance_role_Id IS NULL
							AND r.roleid = T.task_role_id
						)
					)
		INNER JOIN	dbo.team_task_user_preference AS tup
					ON tup.task_id = T.task_id
		LEFT JOIN	dbo.team_training_resource AS TR
					ON  T.task_id = TR.task_id
					AND TR.language_id = @language_id
					AND TR.rec_status = 1
		LEFT JOIN	dbo.team_training_method AS TM
					ON TR.training_method_id = TM.training_method_id
					AND TM.rec_status = 1
		WHERE		T.ti_locked_by IS NULL
		AND		r.userid = @user_id
		AND		tup.[user_id] = @user_id
		AND		tup.rec_status = 1
		AND		r.rec_status = 1
		AND		T.ti_person IS NULL
		AND		(
					T.skill_code = r.skill_code
					OR T.skill_code IS NULL
				)
	) AS S
WHERE	n <= 10
En terme de fréquence j'ai des résultats identiques plus fréquemment, mais après certaines exécutions, le problème revient.

En tout cas merci pour la suggestion !

Est-ce à dire que SQL Server collecterait le TOP des "sous-requêtes" pour les assembler ensuite avant de les retourner au client ?

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 13h04   #8
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 724
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 724
Points : 6 848
Points : 6 848
Ton problème est intéressant mais tu n'aurais pas un jeu de données pour voir ...

++
mikedavem est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 13h35   #9
Membre Expert
 
Avatar de iberserk
 
Homme Bruno IGNACE
Architecte de base de données
Inscription : novembre 2004
Messages : 1 299
Détails du profil
Informations personnelles :
Nom : Homme Bruno IGNACE
Âge : 30
Localisation : France, Gironde (Aquitaine)

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

Informations forums :
Inscription : novembre 2004
Messages : 1 299
Points : 2 282
Points : 2 282
Envoyer un message via MSN à iberserk
Salut,
Quelle version de SqlServer? quel sp?

As tu essayé avec MAXDOP à 1 ?
__________________
Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
iberserk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 14h19   #10
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 724
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 724
Points : 6 848
Points : 6 848
Citation:
As tu essayé avec MAXDOP à 1 ?
-->

Citation:
Je viens de trouver qu'en empêchant SQL Server d'utiliser la parallélisation à l'aide de l'indicateur de requête OPTION (MAXDOP 1), j'ai des résultats identiques de façon consistante.


++
mikedavem est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 20/12/2011, 15h33   #11
Membre Expert
 
Avatar de iberserk
 
Homme Bruno IGNACE
Architecte de base de données
Inscription : novembre 2004
Messages : 1 299
Détails du profil
Informations personnelles :
Nom : Homme Bruno IGNACE
Âge : 30
Localisation : France, Gironde (Aquitaine)

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

Informations forums :
Inscription : novembre 2004
Messages : 1 299
Points : 2 282
Points : 2 282
Envoyer un message via MSN à iberserk
oups pardon.

__________________
Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
iberserk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 16h08   #12
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 670
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

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

Informations forums :
Inscription : janvier 2005
Messages : 4 670
Points : 8 732
Points : 8 732
Pas grave

Je suis sous SQL Server 2008 R2.
Je ne peux pas donner de jeu de données sans dévoiler le métier de l'entreprise qui m'emploie ...

Merci à tous pour votre aide

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2011, 17h03   #13
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 724
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 724
Points : 6 848
Points : 6 848
Tu abuses .. tu pourrais anonymiser les données quand même ...
mikedavem est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2011, 17h33   #14
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 959
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 959
Points : 17 791
Points : 17 791
Le problème c'est qu'il ne sait pas anonymiser le thaï... parce qu'il ne sait pas l'écrire !!!

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2011, 18h40   #15
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 435
Points : 10 435
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Il faudrait rechercher dans de plus vieilles discussions, mais SergeJack obtenait de bonnes performances en passant des TOP via des CROSS APPLY, c'est peut-être applicable ici.

Citation:
Envoyé par elsuket Voir le message
J'ai donc créé une vue indexée (le code dans quelques lignes), et j'ai changé l'horrible OR de la jointure en UNION.
Je le vois toujours l'horrible OR, ici, il ne faut pas faire le travail à moitié
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dbo.team_task_claim AS T
INNER JOIN dbo.auth_user_in_role AS r
  ON r.roleid = T.task_instance_role_Id
			 (
				(
					T.task_instance_role_Id IS NOT NULL
					AND r.roleid = T.task_instance_role_Id
				)
				OR
				(
					T.task_instance_role_Id IS NULL
					AND r.roleid = T.task_role_id
				)
			)
 AND r.userid = @user_id
 AND r.rec_status = 1
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 20h14.


 
 
 
 
Partenaires

Hébergement Web