2012-06-05 38 views
8

我有一個表格變量,並使用「插入 - 選擇」語句在其中插入一些值。 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 @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行查詢需要3秒,否則 - 很長一段時間。

編輯:這裏是我的執行計劃 - 大部分的成本是表掃描,但爲什麼插入是製作需要這麼多時間,並且沒有它,碰巧快速?

enter image description here

後續是我的新的內聯函數:

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 

我再次運行緩慢。任何想法如何優化它?

+3

使用查詢分析器的「解釋計劃」按鈕向您顯示正在採取的時間。 –

+0

@JeffWatkins我將附上執行計劃的屏幕截圖到我的問題。 – gotqn

+0

如果您選擇進入臨時表,會發生什麼情況? –

回答

11

插入表變量的查詢不能有並行計劃。

嘗試使用#temp表替代以允許SELECT並行化。

+0

@Joro - 你可以將它重寫爲內聯TVF而不是多語句嗎?那麼這將避免需要插入到中間表變量中。這意味着您將查詢重寫爲單個語句。使用CTE或派生表來替換'@TableTable'的角色 –

+0

@MartinSmith我可以使用任何類型的函數,但我認爲返回表的唯一方法是這樣的? – gotqn

+0

@Joro - 沒有兩種不同類型的TVF。內聯函數的效率更高,因爲它們被優化器內聯,但需要在單個SQL語句中表示邏輯。 –