2016-02-17 90 views
6

User-Defined Table Typesを使用して、整数リストをストアドプロシージャに渡しました。SQL Serverのユーザー定義テーブル型のパフォーマンス

これらを使用して、ストアドプロシージャクエリの他のテーブルに結合します。

たとえば:大きなデータセットを使用している場合

CREATE PROCEDURE [dbo].[sp_Name] 
(
    @Ids [dbo].[OurTableType] READONLY 
) 
AS 
    SET Nocount ON 

    SELECT 
     * 
    FROM 
     SOMETABLE 
     INNER JOIN @Ids [OurTableType] ON [OurTableType].Id = SOMETABLE.Id 

私たちは、このことから非常に悪いパフォーマンスを見てきました。

私たちは物事をスピードアップするために使用したアプローチの1つとして、内容を一時テーブルにダンプし、その代わりに参加します。例えば

は:

CREATE PROCEDURE [dbo].[sp_Name] 
(
    @Ids [dbo].[OurTableType] READONLY 
) 
AS 
    SET Nocount ON 
    CREATE TABLE #TempTable(Id INT) 
    INSERT INTO #TempTable 
    SELECT Id from @Ids 

    SELECT 
     * 
    FROM 
     SOMETABLE 
     INNER JOIN #TempTable ON #TempTable.Id = SOMETABLE.Id 

    DROP TABLE #TempTable 

これは、パフォーマンスを大幅に向上させるんが、私は、このアプローチにいくつかの意見と私たちは考えられていない任意の他の結果を取得したいです。また、これがパフォーマンスを向上させる理由についての説明も役立つかもしれません。

N.B.時には、整数以上のものを渡す必要があるかもしれません。そのため、コンマ区切りのリストなどを使用しないのはなぜですか。

+0

質問:このリストは、アプリケーション層、または別のsprocから渡していますか?一時テーブルとテーブル変数について書かれた記事がたくさんあります。 http:// stackoverflow。com/questions/27894/whats-the-difference-temp-table-and-table-variable-in-sql-serverとhttp://www.sql-server-performance.com/2007/temp- tables-vs-variables/ – Jeremy

+0

はい、アプリケーション層からリストを渡しています。記事をありがとう。 – KMB

答えて

7

このトピックは前に説明しました。 JOINのパフォーマンスが低い主な理由は、テーブル値パラメータ(TVP)がテーブル変数であることです。表変数は統計を保持せず、Query Optimizerには1行しかないように見えます。したがって、彼らはちょうどINSERT INTO Table (column_list) SELECT column_list FROM @TVP;のようなものをやっても結構ですが、JOINはありません。

これを回避しようとするいくつかのことがあります。

  1. は(すでにこれをやっている)ローカルの一時テーブルにすべてをダンプします。ここでの技術的な欠点は、TVPに渡されたデータをtempdb(TVPテーブルとテンポラリテーブルの両方にデータを格納する)に複製していることです。

  2. クラスタ化されたプライマリキーを持つようにユーザー定義テーブルタイプを定義してみることがあります。あなたが[Id]フィールド上のこのインラインを行うことができます。

    [ID] INT NOT NULL PRIMARY KEY 
    

    これはパフォーマンスが向上しますどのくらい確かに、しかし、試してみる価値はありません。

  3. OPTION (RECOMPILE)をクエリに追加できます。これは、適切な見積もりを持つことができるように、テーブル変数にある行の数を確認するためにQuery Optimizerを取得する方法です。

    SELECT column_list 
    FROM SOMETABLE 
    INNER JOIN @Ids [OurTableType] 
         ON [OurTableType].Id = SOMETABLE.Id 
    OPTION (RECOMPILE); 
    

    ここでの欠点は、このプロシージャが呼び出されるたびに時間がかかるRECOMPILEがあることです。しかし、それは全体的な純利益であるかもしれません。

PS。 SELECT *をしないでください。必ず列リストを指定してください。 IF EXIST(SELECT * FROM)...のようなことをしない限り。

+0

提案してくれてありがとう、私たちは2&3を改善してテストしました。しかし、この場合でもオプション1が最も速いです。私はデータの複製のオーバーヘッドを理解しています。 – KMB

関連する問題