2012-06-05 20 views
8

Bir tablo değişkenim var ve ona "Insert Into - Select" deyimini kullanarak bazı değerler ekliyorum. Seçim, birkaç birleştirmenin birleşimidir ve ayrı olarak çalıştırıldığında 3 saniye sürer. Sorun, bütün kodun yürütülmesi için 3-4 dakika sürmesidir. Bunun için özel bir neden var mı diye merak ediyorum.T-SQL Insert - Tablo içinde değişken çok yavaş

Bu benim tablo değişken beyanıdır:

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) 
) 

Sanırım bazı verilerle başlatmak bir başka tablo değişkeni var ve bu onun yapısı şöyledir:

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

ve aşağıdaki kodu benim sorun bildirimi (seçime ekle):

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 

Daha önce de söylediğim gibi, Sert çizgi sorgu, aksi takdirde 3 saniye sürüyor - çok uzun bir süre.

DÜZENLEME: İşte yürütme planım - maliyetin çoğu tablo taramasıdır, ancak ekleme yapıldığında neden bu kadar çok zaman alır ve onsuz hızlı olur?

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 

yavaşça tekrar çalıştırır:

enter image description here

takip benim yeni satır içi fonksiyonudur. Herhangi bir fikir nasıl optimize edilir?

+3

Query Analyzer'ın "planını açıkla" düğmesini kullanarak zamanın nerede çekildiğini gösterin. –

+0

@JeffWatkins Sorularıma planım ile ekran görüntüsü ekleyeceğim. – gotqn

+0

Geçici masaya seçerseniz ne olur? –

cevap

11

Tablo değişkenlerine eklenen sorgular paralel bir plana sahip olamaz.

#temp tablosunu kullanarak, SELECT kodunun paralelleştirilmesine izin verin.

+0

@Joro - Çoklu ifadelerden ziyade satır içi TVF olmak için yazabilir misiniz? Daha sonra bu, ara tablo değişkenine hiç ekleme ihtiyacını ortadan kaldıracaktır. Sorguyu tek bir ifade olarak yeniden yazmanız gerektiği anlamına gelir. CTT veya türetilmiş bir tablo kullanarak '@ TempTable' –

+0

@MartinSmith rolünü değiştirmek için herhangi bir işlev türünü kullanabilirim, ancak tablo döndürmenin tek yolu bu muydu? – gotqn

+0

@Joro - Hayır iki farklı TVF var. Inline olanlar, optimiser tarafından belirtildiği gibi daha verimlidir, ancak mantıksal bir SQL deyiminde ifade edilebilir olması gerekir. –