2012-06-05 7 views
8

Tengo una variable de tabla y estoy insertando en ella algunos valores usando la instrucción "Insertar en - Seleccionar". La selección es una combinación de pocas uniones, y cuando se ejecuta por separado, tarda 3 segundos. El problema es que todo el código tarda 3-4 minutos en ejecutarse. Me pregunto si hay alguna razón en particular para esto.Insertar T-SQL - Seleccionar en la variable Tabla es muy lento

Este es el mi tabla de declaración de variables:

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

tengo una otra variable mesa que inicializo con algunos datos, y esto es su estructura:

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

y el código siguiente es mi declaración del problema (insertar en - seleccionar):

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 

Como dije antes, si comento el en La línea de búsqueda tarda 3 segundos, de lo contrario, un tiempo muy largo.

EDITAR: Aquí está mi plan de ejecución: la mayor parte del costo es el escaneo de tabla, pero ¿por qué tarda tanto tiempo cuando se realiza inserción, y pasa a ser rápido sin él?

enter image description here

El seguimiento es mi nueva función en línea:

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 

i varía lentamente de nuevo. ¿Alguna idea de cómo optimizarlo?

+3

Utilice el botón "explicar plan" de Query Analyzer para mostrarle dónde se está tomando el tiempo. –

+0

@JeffWatkins Voy a adjuntar una captura de pantalla con el plan de ejecución a mi pregunta. – gotqn

+0

¿Qué sucede si selecciona en una tabla temporal? –

Respuesta

11

Las consultas que se insertan en variables de tabla no pueden tener un plan paralelo.

Pruebe utilizar una tabla #temp para permitir que el SELECT se paralelice.

+0

@Joro - ¿Se puede volver a escribir para que sea una TVF en línea en lugar de una declaración de varias? Entonces eso evitará la necesidad de insertar en la tabla intermedia variable en absoluto. Significa que reescribe la consulta para que sea una sola declaración. Usando un CTE o una tabla derivada para reemplazar el rol de '@ TempTable' –

+0

@MartinSmith Puedo usar cualquier tipo de función, pero he pensado que la única manera de devolver la tabla es esta? – gotqn

+0

@Joro - No hay dos tipos diferentes de TVF. Los en línea son más eficientes a medida que el optimizador los incorpora, pero necesitan que la lógica se pueda expresar en una sola instrucción SQL. –