2012-06-05 48 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语句中表示逻辑。 –