Les Multiples de la JOINTURE INTERNE est trop lent SQL SERVER
Je vais avoir un problème de performance.
J'ai créé une table qui reçoit des données à partir d'un fichier, je fais un BULK INSERT
. Puis-je faire un SELECT
avec plusieurs INNER JOIN
s (11 jointures internes) pour les insérer dans une autre table avec les bonnes données.
Lorsque j'exécute ce SELECT
, il prend trop de temps (plus d'une heure), puis-je l'arrêter. Ma solution était de sortir de cette requête en 3, de la création de @temp
tables. À ma grande surprise, cela prend 3 minutes. C'est ce que j'essaie de comprendre, POURQUOI me casser la requête en 3 a été plus RAPIDE que celui de l'instruction select. Voici ma requête:
SELECT t1.ReturnINT, t1.ReturnBIT, t2.ReturnINT, t3.ReturnINT, t5.ReturnINT, t1.ReturnDateTime
FROM t1
INNER JOIN t2
ON t2.my_column_varchar = t1.my_column_varchar
INNER JOIN t3
ON t3.my_column_number = t1.my_column_number AND t2.my_column_ID = t3.my_column_ID
INNER JOIN t4
ON t4.my_column_varchar = t1.my_column_varchar
INNER JOIN t5
ON t5.my_column_int = t1.my_column_int AND t5.my_column_int = t4.my_column_int AND t2.my_column_int = t5.my_column_int
INNER JOIN t6
ON t6.my_column_int = t5.my_column_int AND t6.my_column_int = t2.my_column_int
INNER JOIN t7
ON t7.my_column_int = t6.my_column_int
INNER JOIN t8
ON t8.my_column_int = t3.my_column_int AND t8.my_column_datetime = t1.my_column_datetime
INNER JOIN t9
ON t9.my_column_int = t3.my_column_int AND t8.my_column_datetime BETWEEN t9.my_column_datetime1 AND t9.datetime1 + t9.my_column_datetime2
INNER JOIN t10
ON t10.my_column_int = t9.my_column_int AND t10.my_column_int = t6.my_column_int
INNER JOIN t11
ON t11.my_column_int = t9.my_column_int AND t8.my_column_datetime = t11.my_column_datetime
----MODIFIÉ----
Il n'y a PAS de clause where, ma requête est exactement comme je l'ai mis ici.
Voici ma cassé des requêtes sur, j'ai oublié de les mettre ici. Il s'exécute en 3 minutes.
DECLARE @temp TABLE (
<Some_columns>
)
INSERT INTO @temp
SELECT <My_Linked_Columns>
FROM t1
INNER JOIN t2
ON t2.my_column_varchar = t1.my_column_varchar
INNER JOIN t3
ON t3.my_column_number = t1.my_column_number AND t2.my_column_ID = t3.my_column_ID
INNER JOIN t4
ON t4.my_column_varchar = t1.my_column_varchar
INNER JOIN t5
ON t5.my_column_int = t1.my_column_int AND t5.my_column_int = t4.my_column_int AND t2.my_column_int = t5.my_column_int
DECLARE @temp2 TABLE(
<Some_Columns>
)
INSERT INTO @temp2
SELECT <More_Linked_Columns>
FROM @temp as temp
INNER JOIN t6
ON t6.my_column_int = temp.my_column_int AND t6.my_column_int = temp.my_column_int
INNER JOIN t7
ON t7.my_column_int = t6.my_column_int
INNER JOIN t8
ON t8.my_column_int = temp.my_column_int AND t8.my_column_datetime = temp.my_column_datetime
DECLARE @temp3 TABLE(
<Some_Columns>
)
INSERT INTO @temp3
SELECT <More_Linked_Columns>
FROM @temp2 AS temp2
INNER JOIN t9
ON t9.my_column_int = temp2.my_column_int AND temp2.my_column_datetime BETWEEN t9.my_column_datetime1 AND t9.datetime1 + t9.my_column_datetime2
INNER JOIN t10
ON t10.my_column_int = t9.my_column_int AND t10.my_column_int = temp2.my_column_int
INNER JOIN t11
ON t11.my_column_int = t9.my_column_int AND temp2.my_column_datetime = t11.my_column_datetime
SELECT <All_Final_Columns>
FROM @temp3
----ÉDITÉS 3----
Étudier plus en plus de choses, j'ai découvert un problème dans l'exécution du plan. J'ai une Boucle Imbriquée que les estimations 1 rangée, mais il retourne en fait 1.204.014 lignes. Je crois que le problème est exactement ici, mais je n'ai pas trouvé comment résoudre ce problème sans casser ma requête en 3 parties (Maintenant je sais pourquoi casse, il est plus rapide hehehe)
Il réduit le choix de l'Optimiseur de décider de l'ordre de jointure et le type de jointure
OriginalL'auteur Alexandre_Almeida | 2015-08-07
Vous devez vous connecter pour publier un commentaire.
Raisons les plus communes:
Raison 1: Lorsque deux tables ayant n et m lignes participant à
INNER JOIN
ont beaucoup de beaucoup de relation, alors laINNER JOIN
peut près unCROSS JOIN
et peuvent produire un résultat plus que MAX(n,m) des lignes, théoriquement n x m lignes sont possibles.Maintenant imaginer que beaucoup de ces tables dans
INNER JOIN
.Ainsi, dans l'ensemble de résultats de plus en plus grand et va commencer à manger dans la zone de mémoire allouée.
Cela pourrait être une raison pourquoi les tables temporaires pourraient vous aider.
Raison 2: Vous n'avez pas
INDEX
construit sur les colonnes de la jointure de tables.Raison 3: avez-vous des fonctions dans
WHERE
clause?OriginalL'auteur DhruvJoshi
En général, vous voulez que l'optimiseur de requête pour joindre les tables de telle manière à limiter le jeu de résultats autant que possible. Si vous avez Une table avec 1 million de lignes, le tableau B avec 1 million de lignes, et le tableau C avec 10 lignes, vous souhaitez jointure interne à partir de la table de C à A ou B tout d'abord, ce serait vous donner à plus de 10 enregistrements (en supposant que 1:1 match) pour ensuite se joindre à la dernière table. Si vous avez adhéré à Un B tout d'abord, vous seriez de joindre tous les 1 millions de lignes de chaque, ce qui pourrait prendre un peu plus longue.
Généralement l'optimiseur de requête est "assez bon" lors de la cueillette de l'ordre de jointure, mais dans votre cas, il ne l'était pas. La meilleure méthode que j'ai vu pour forcer l'ordre de jointure a été démontré par Adam Mécanicien dans un billet de blog ici. Elle implique l'utilisation d'une clause TOP sur les tables que vous souhaitez commencer à le rejoindre. L'optimiseur de requête obtiendrez alors le résultat de ces tableaux premier, et vous pouvez vraiment limiter le nombre total de lignes et d'augmenter les performances des requêtes. J'utilise cette méthode chaque fois que possible.
OriginalL'auteur Dave.Gugg
Avec le droit de l'indice ou des indices de l'original de la requête doit s'exécuter très rapidement (à moins de une seconde, si vous avez de la page de données). Ne pas utiliser des tables temporaires comme un hack pour ne pas être en mesure de venir avec une requête raisonnable.
OriginalL'auteur John