Bonjour à tous.
Domaine : base de données analytiques
SGBD : SQL Server 2005 et SQL Server 2008 (mais si la solution trouvé est que pour 2008 ça m'ira)
Voici mon objectif :
Insérer de nombreuses lignes (Plusieurs millions) dans une table existante le plus rapidement possible.
Option :
en acceptant les insertion concurrente et les accès concurrent à la table via un select (update et delete non utilisé). Sachant qu'on ne peut pas essayer d'inserer deux fois la meme chose (normal car y a la PK) et on ne peut pas essayer de sélectionner des datas qui sont en train d'être insérées.
Table dans laquelle inserer :
Stats de l'index a jour quotidiennement
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 table maTableDest ( Champ1 int not null, Champ2 int not null, Champ3 int not null, Champ4 int not null ) PRIMARY KEY CLUSTERED ( [Champ1] ASC, [Champ2] ASC, [Champ3] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
Fragmentation de l'index : 0 %
Genre de requete pour inserer les donner
Ce que j'ai essayé :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 Insert into maTableDest Select distinct 'valeur en dur' as Champ1 ,C2 as Champ2 ,C3 as Champ3 ,C4 as Champ4 FROM uneTable with(nolock) INNER JOIN .... WHERE ....
Insert into maTableDest with(tablock)
Select distinct 'valeur en dur' as Champ1
,C2 as Champ2
,C3 as Champ3
,C4 as Champ4
FROM uneTable with(nolock)
INNER JOIN ....
WHERE ....
L'avantage du tablock est que j'augmente de façon importante la vitesse d'insertion (2x plus rapide et l'impact est de plus en plus important avec la volumétrie), les performances sont équivalentes a une insertion dans une table temporaire :
Mais les accès concurrents sont lockés avec le tablock (c'est le principe d'un côté).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 Select distinct 'valeur en dur' as Champ1 ,C2 as Champ2 ,C3 as Champ3 ,C4 as Champ4 INTO #Temp FROM uneTable with(nolock) INNER JOIN .... WHERE ....
De plus si je fais :
Avec en parallèle, une insertion (lancée en 2eme), l'insertion est locké et la les temps explosent :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 select * from maTableDest with(nolock) where ...
3 fois plus de temps que si l'insertion était seul. Je me dit que ça vient du fait que le select
pose des lock sur les lignes, requete et enlève les locks (1 à 1 car par ligne)
Je me demandé si le fait d'augmenté la granularité des lock (locké au niveau page voir table) au
lieu de row pouvait être interessant.
J'ai testé le paramètre :qui permet de limité l'écriture de log lors
Code : Sélectionner tout - Visualiser dans une fenêtre à part RECOVERY à BULK_LOGGED
d'insertion notamment mais l'impact n'est pas présent.
Effectivement, il me semble qu'il faut que la table soit vide pour que le bulk-logged soit vraiment
utilisé. A moins que je me sois trompé dans mon paramètrage.
Donc avez vous d'autres pistes ?
Partager