web-dev-qa-db-fra.com

Y a-t-il des avantages à utiliser des tables temporaires par rapport aux tables dérivées dans SQL Server?

J'ai lu que les tables dérivées ont de meilleures performances que les tables temporaires, mais de toute façon de nombreux développeurs SQL Server préfèrent les seconds. Pourquoi? Je dois faire des requêtes avec des données volumineuses (millions d'enregistrements) et je veux être sûr d'utiliser le meilleur choix.

CREATE TABLE A(
    id BIGINT IDENTITY(1,1) NOT NULL,
    field1 INT NOT NULL,
    field2 VARCHAR(50) NULL,
);

CREATE TABLE B(
    id INT IDENTITY(1,1) NOT NULL,
    field1 VARCHAR(10) NULL,
    field2 INT NULL
);

INSERT INTO A 
    (field1,field2)
VALUES 
    (1,'a'),(2,'b'),(3,'c'),(2,'d'),(5,'e'),
    (6,'f'),(7,'g'),(8,'h'),(9,'i'),(2,'j');

INSERT INTO B 
    (field1,field2)
VALUES 
    ('a',1),('b',2),('c',3),('d',4),('e',5),
    ('f',6),('g',7),('h',8),('i',9),('j',2),('k',3);

DECLARE @begin INT=0,@end INT=200;

Tableaux dérivés

/*derived tables*/
SELECT 
    C.id,C.field1,C.field2,C.field3 
FROM
(
    SELECT
        A.id,A.field1,A.field2,B.field2 AS field3, 
        ROW_NUMBER() OVER (ORDER BY A.id) AS iRow
    FROM 
        A INNER JOIN B ON A.field1=B.id
) C
WHERE iRow BETWEEN @begin AND @end;

Tables temporaires

/*temporary tables*/
CREATE TABLE #C (
    iRow INT IDENTITY(1,1),
    id bigint,
    field1 INT,
    field2 VARCHAR(50),
    field3 INT );

INSERT INTO #C 
    (id,field1,field2,field3)
SELECT TOP 1000 
    A.id,A.field1,A.field2,B.field2 
FROM  
    A INNER JOIN B ON A.field1=B.id
ORDER BY 
    A.id;

SELECT id,field1,field2,field3 
FROM #C 
WHERE iRow BETWEEN @begin AND @end;

DROP TABLE #C;
8
norgematos

@ user16484 vous a déjà dirigé vers Lequel ont de meilleures performances: Tables dérivées ou Tables temporaires dans le commentaire.

Voir aussi Temp Table 'vs' Table Variable 'vs' CTE. qui couvre également les tables dérivées.

Un résumé rapide: les tables #temp peuvent être indexées, peuvent avoir des index/contraintes UNIQUES, peuvent être des références plusieurs fois dans la même requête, peuvent être référencées (FROM ou JOIN) par plusieurs requêtes. Les tables dérivées peuvent être référencées (FROM ou JOIN) une fois dans une requête.

En termes de performances, retirez Profiler for SQL: BatchCompleted et RPC: Completed, regardez les colonnes Lecture, Écriture, CPU et Durée, et voyez ce que quelques exécutions de tables dérivées vs #temp tables vs indexées #temp tables font pour chaque requête particulière.

En général - si vous comptez l'utiliser plusieurs fois, la table #temp l'emporte. Si vous rejoignez un grand nombre de tables, la table #temp gagne probablement. Si vous rejoignez seulement quelques tables, la table dérivée a une chance raisonnable de gagner. Benchmark it!

6
Anti-weakpasswords

En général, cela dépend de vos requêtes particulières et de la taille des résultats temporaires.

Pour le scénario spécifique donné, qui est la pagination, les tables temporaires sont totalement inutiles. Pourquoi voudriez-vous enregistrer 1000 lignes dans une table temporaire pour ensuite retourner le 1er 200? L'utilisation d'une table "dérivée" ou d'un CTE dans ce scénario est beaucoup plus efficace, car l'ensemble de résultats complet n'a pas besoin d'être stocké n'importe où, ou dans la plupart des cas, même produit. Par exemple, lors de la demande de la 1ère page de 200 lignes, seules les 200 premières lignes devront être extraites des tables de base (en supposant que les index existants peuvent prendre en charge l'ordre de tri demandé dans la requête).

6
Vlad G.