web-dev-qa-db-ja.com

SQL Serverで派生テーブルよりも一時テーブルを使用する利点はありますか?

派生テーブルは一時テーブルよりもパフォーマンスが優れていますが、とにかく多くのSQL Server開発者は2番目のテーブルを好みます。どうして?大量のデータ(数百万のレコード)でクエリを実行する必要があり、最良の選択を使用していることを確認したい。

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;

派生テーブル

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

一時テーブル

/*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はすでに パフォーマンスが優れているもの:派生テーブルまたは一時テーブル をコメントで示しています。

また、派生テーブルもカバーする Temp Table 'vs' Table Variable 'vs' CTE。 も参照してください。

簡単な要約:#tempテーブルにはインデックスを作成でき、一意のインデックス/制約を設定でき、同じクエリで複数回参照でき、複数のクエリで参照(FROMまたはJOIN)できます。派生テーブルは、1回のクエリで一度参照(FROMまたはJOIN)できます。

パフォーマンスの観点から、Profiler for SQL:BatchCompletedおよびRPC:Completedを引き出し、読み取り、書き込み、CPU、および期間の列を見て、派生テーブルのいくつかの実行と#tempテーブルとインデックス付き#tempテーブルの違いを確認します。特定の各クエリ。

一般に、これを複数回使用する場合は、#temp tableが優先されます。多数のテーブルを結合する場合は、おそらく#temp tableが優先されます。少数のテーブルのみを結合する場合、派生テーブルが勝つ合理的なチャンスがあります。それをベンチマーク!

6

一般に、特定のクエリと一時的な結果のサイズによって異なります。

与えられた特定のシナリオ(ページング)では、一時テーブルは完全に不要です。 1000行を一時テーブルに保存して最初の200行を返すのはなぜですか?このシナリオで「派生」テーブルまたはCTEを使用すると、完全な結果セットをどこにも保存する必要がなく、ほとんどの場合生成する必要もないため、はるかに効率的です。たとえば、200行の最初のページを要求する場合、最初の200行のみをベーステーブルから取得する必要があります(既存のインデックスがクエリで要求された並べ替え順序をサポートできる場合)。

6
Vlad G.