2012-06-05 15 views
8

私はテーブル変数を持っており、 "Insert Into - Select"ステートメントを使っていくつかの値を挿入しています。選択は少数の結合の組み合わせであり、別々に実行される場合は3秒かかる。問題は、コード全体が3〜4分かかることです。それには特別な理由があるのだろうか?T-SQL挿入 - テーブル変数の選択が非常に遅い

これは私のテーブル変数の宣言です:私はいくつかのデータを初期化し、他のテーブル変数を持ち、これは、その構造である

DECLARE @Result TABLE 
(
    ProductID NVARCHAR(25) PRIMARY KEY 
    ,ProductName NVARCHAR(100) 
    ,ProductCategoryID TINYINT 
    ,ProductCategory NVARCHAR(50) 
    ,ProductSubCategoryID TINYINT 
    ,ProductSubCategory NVARCHAR(50) 
    ,BrandID TINYINT 
    ,Brand NVARCHAR(50) 
) 

DECLARE @TempTable TABLE 
(
    ProtoSurveyID INT, 
    ProductID NVARCHAR(25) PRIMARY KEY 
) 

、次のコードは、私の問題のステートメント(insert into - select):

INSERT INTO @Result (ProductID,ProductName,ProductCategoryID,ProductCategory,ProductSubCategoryID,ProductSubCategory,BrandID,Brand) 
SELECT 
     Products.ProductID AS ProductID 
     ,Products.ProductName AS ProductName 
     ,ProductCategories.ProductCategoryID AS ProductCategoryID 
     ,ProductCategories.ProductCategory AS ProductCategory 
     ,ProductSubCategories.ProductSubCategoryID AS ProductSubCategoryID 
     ,ProductSubCategories.ProductSubCategory AS ProductSubCategory 
     ,Brands.BrandID AS BrandID 
     ,Brands.Brand AS Brand 
FROM 
(
     SELECT  
       CAST(A.Col001 AS tinyint) AS ProductCategoryID 
       ,CAST(A.Col002 AS tinyint) AS BrandID 
       ,CAST(A.Col003 AS nvarchar(25)) AS ProductID 
       ,CAST(A.Col004 AS nvarchar(100)) AS ProductName 
       ,CAST(A.Col006 As tinyint) AS ProductSubCategoryID 
       ,B.ProtoSurveyID 
     FROM DataSetsMaterializedDataSqlvariant A 
     INNER JOIN @TempTable B 
     ON B.ProductID=CAST(A.Col003 AS nvarchar(25)) 
     WHERE DataSetsMaterializedInternalRowsetID = 3 
) Products  
INNER JOIN 
(
     SELECT CAST(A.Col001 AS tinyint) AS BrandID 
       , CAST(A.Col002 AS nvarchar(50)) AS Brand 
     FROM DataSetsMaterializedDataSqlvariant A 
     WHERE DataSetsMaterializedInternalRowsetID = 1 
)Brands On Products.BrandID=Brands.BrandID 
INNER JOIN 
(
     SELECT CAST(A.Col001 AS tinyint) AS ProductCategoryID 
       ,CAST(A.Col002 AS nvarchar(50)) AS ProductCategory 
     FROM DataSetsMaterializedDataSqlvariant A 
     WHERE DataSetsMaterializedInternalRowsetID = 2 
) ProductCategories On Products.ProductCategoryID=ProductCategories.ProductCategoryID 
INNER JOIN 
(
     SELECT CAST(A.Col001 AS tinyint) AS ProductSubCategoryID 
       , CAST(A.Col002 AS nvarchar(50)) AS ProductSubCategory 
     FROM DataSetsMaterializedDataSqlvariant A 
     WHERE DataSetsMaterializedInternalRowsetID = 11 
) ProductSubCategories on Products.ProductSubCategoryID=ProductSubCategories.ProductSubCategoryID 

私が前に言ったように、 sert lineクエリには3秒かかります。それ以外の場合は非常に長い時間です。

EDIT:これは私の実行計画です - コストの大部分はテーブルスキャンですが、なぜ挿入に時間がかかっていて、それがなくても素早く発生しますか?

CREATE FUNCTION [dbo].[fn_XxCustom_RetailAudits_GetProductsForFilter] 
(
    @SecurityObjectUserID BIGINT 
) 
RETURNS TABLE 
AS 
RETURN 

    WITH CTE(ProtoSurveyID,ProductID) AS 
    (
     SELECT DISTINCT CAST(B.ProtoSurveyID AS INT) 
         ,CAST(A.Col002 AS NVARCHAR(25)) AS ProductID 
     FROM DataSetsMaterializedDataSqlvariant A 
     JOIN SurveyInstances B ON A.Col001=B.SurveyInstanceID AND CAST(B.ProtoSurveyID AS INT) IN (SELECT ProtoSurveyID FROM dbo.fn_Filter_GetProtoSurveysAllowedShort(@SecurityObjectUserID, 'CLIENTACCESS',NULL)) 
     WHERE DataSetsMaterializedInternalRowsetID = 5 
    ) 
    SELECT 
      Products.ProductID AS ProductID 
      ,Products.ProductName AS ProductName 
      ,ProductCategories.ProductCategoryID AS ProductCategoryID 
      ,ProductCategories.ProductCategory AS ProductCategory 
      ,ProductSubCategories.ProductSubCategoryID AS ProductSubCategoryID 
      ,ProductSubCategories.ProductSubCategory AS ProductSubCategory 
      ,Brands.BrandID AS BrandID 
      ,Brands.Brand AS Brand 
    FROM 
    (
      SELECT  
        CAST(A.Col001 AS tinyint) AS ProductCategoryID 
        ,CAST(A.Col002 AS tinyint) AS BrandID 
        ,CAST(A.Col003 AS nvarchar(25)) AS ProductID 
        ,CAST(A.Col004 AS nvarchar(100)) AS ProductName 
        ,CAST(A.Col006 As tinyint) AS ProductSubCategoryID 
        ,B.ProtoSurveyID 
      FROM CTE B 
      INNER JOIN DataSetsMaterializedDataSqlvariant A 
      ON B.ProductID=CAST(A.Col003 AS nvarchar(25)) 
      WHERE DataSetsMaterializedInternalRowsetID = 3 
    ) Products  
    INNER JOIN 
    (
      SELECT CAST(A.Col001 AS tinyint) AS BrandID 
        ,CAST(A.Col002 AS nvarchar(50)) AS Brand 
      FROM DataSetsMaterializedDataSqlvariant A 
      WHERE DataSetsMaterializedInternalRowsetID = 1 
    )Brands On Products.BrandID=Brands.BrandID 
    INNER JOIN 
    (
      SELECT CAST(A.Col001 AS tinyint) AS ProductCategoryID 
        ,CAST(A.Col002 AS nvarchar(50)) AS ProductCategory 
      FROM DataSetsMaterializedDataSqlvariant A 
      WHERE DataSetsMaterializedInternalRowsetID = 2 
    ) ProductCategories On Products.ProductCategoryID=ProductCategories.ProductCategoryID 
    INNER JOIN 
    (
      SELECT CAST(A.Col001 AS tinyint) AS ProductSubCategoryID 
        ,CAST(A.Col002 AS nvarchar(50)) AS ProductSubCategory 
      FROM DataSetsMaterializedDataSqlvariant A 
      WHERE DataSetsMaterializedInternalRowsetID = 11 
    ) ProductSubCategories on Products.ProductSubCategoryID=ProductSubCategories.ProductSubCategoryID 

GO 

私はゆっくりと再び実行します:

enter image description here

フォローは私の新しいインライン関数です。任意のアイデアをどのように最適化するには?

+3

クエリアナライザーの「計画の実行」ボタンを使用して、時間の所在を表示します。 –

+0

@JeffWatkins私は質問に実行計画のスクリーンショットを添付します。 – gotqn

+0

一時テーブルを選択するとどうなりますか? –

答えて

11

テーブル変数に挿入するクエリは、並列プランを持つことはできません。

代わりに#tempテーブルを使用して、SELECTを並列化できるようにしてください。

+0

@Joro - マルチステートメントではなくインラインTVFに書き換えることができますか?そうすれば、中間テーブル変数に変数を挿入する必要がなくなります。これは、クエリを単一のステートメントに書き換えることを意味します。 CTEまたは派生テーブルを使用して@ TempTableの役割を置換する –

+0

@MartinSmithどのようなタイプの関数も使用できますが、テーブルを返す唯一の方法はこれだと思いますか? – gotqn

+0

@Joro - いいえ、2種類のTVFがあります。インラインのものはオプティマイザによってインライン展開されるので効率的ですが、ロジックを単一のSQL文で表現可能にする必要があります。 –