为了获得实体的“描述”列,我需要连接多个表。内部连接在一开始就足够了,但现在需求已经改变了,我需要从包含“描述”列的表中获取多行,所以我创建了一个表值函数。
问题是查询执行得更糟。使用内部连接时,需要1秒钟,现在需要30秒。
如何优化效果?
我知道使用外部应用会返回比内部连接更多的行。
我尝试在AGREEMENT_LINE表上添加AGR_LINE_NO和Meta_IsCurrent作为聚簇索引,但这只会提高原始查询的性能。
以下是原始查询,新查询,功能和执行计划。
原始查询:
SELECT TOP 10000
OBJECT_TYPE,
SEQ_NO,
O.AGR_LINE_NO,
SHORT_DESC,
C02,
C03,
C04,
C05,
C07,
C10,
C52,
N05,
N04,
N02,
N19,
N01,
X.[Description] AS CarConcept,
O.[Timestamp] AS OBJ_TIMESTAMP,
O.Record_Timestamp AS OBJ_RECORD_TIMESTAMP,
X.RECORD_TIMESTAMP AS X_RECORD_TIMESTAMP
FROM [Archive].[TIA_TIA_OBJECT] O
INNER JOIN [Archive].[TIA_TIA_AGREEMENT_LINE] A
ON A.AGR_LINE_NO = O.Agr_Line_No
INNER JOIN [Archive].[TIA_TIA_PRODUCT_LINE] PL
ON PL.PRODUCT_LINE_ID = A.PRODUCT_LINE_ID AND PL.PRODUCT_LINE_VER_NO = A.PRODUCT_LINE_VER_NO
INNER JOIN [Archive].[TIA_TIA_TARIFF_STRUCTURE] TS
ON PL.TARIFF_TYPE_LIST_VER = TS.[VERSION] AND PL.PRODUCT_LINE_ID = TS.PRODUCT_LINE_ID
INNER JOIN [Archive].[TIA_TIA_TARIFF_CODES] TC
ON TC.PRODUCT_LINE_ID = PL.PRODUCT_LINE_ID AND TC.[TYPE] = TS.[TYPE] AND TC.[VERSION] = TS.TYPE_VERSION
INNER JOIN [Archive].[TIA_TIA_XLA_PE_REFERENCE] X
ON TC.[TYPE] = X.Table_Name AND PL.PRODUCT_LINE_ID = X.ID AND TC.[VERSION] = X.[VERSION] AND TC.CODE = X.[CODE]
WHERE O.OBJECT_TYPE = 'BIO01'
AND
TC.[TYPE] =
CASE WHEN O.C52 IS NOT NULL
THEN 'XTARIFTYPE'
ELSE 'ART'
END
AND X.[Language] = 'DK'
AND
X.Code =
CASE WHEN O.C52 IS NOT NULL
THEN O.C52
ELSE O.C02
END
AND O.Meta_IsCurrent = 1
AND A.Meta_IsCurrent = 1
AND PL.Meta_IsCurrent = 1
AND TS.Meta_IsCurrent = 1
AND TC.Meta_IsCurrent = 1
AND X.Meta_IsCurrent = 1
新查询:
SELECT TOP 10000
OBJECT_TYPE,
SEQ_NO,
O.AGR_LINE_NO,
SHORT_DESC,
C02,
C03,
C04,
C05,
C07,
C10,
C52,
N05,
N04,
N02,
N19,
N01,
carConcept.CodeDescription AS CarConcept,
O.[Timestamp] AS OBJ_TIMESTAMP,
O.Record_Timestamp AS OBJ_RECORD_TIMESTAMP,
carConcept.RECORD_TIMESTAMP AS X_RECORD_TIMESTAMP
FROM [Archive].[TIA_TIA_OBJECT] O
INNER JOIN [Archive].[TIA_TIA_AGREEMENT_LINE] A
ON A.AGR_LINE_NO = O.Agr_Line_No
INNER JOIN [Archive].[TIA_TIA_PRODUCT_LINE] PL
ON PL.PRODUCT_LINE_ID = A.PRODUCT_LINE_ID AND PL.PRODUCT_LINE_VER_NO = A.PRODUCT_LINE_VER_NO
OUTER APPLY Staging.ufnGetCodeDescription(PL.PRODUCT_LINE_ID, PL.PRODUCT_LINE_VER_NO, PL.TARIFF_TYPE_LIST_VER,
CASE WHEN O.C52 IS NOT NULL
THEN 'XTARIFTYPE'
ELSE 'ART'
END,
CASE WHEN O.C52 IS NOT NULL
THEN O.C52
ELSE O.C02
END) carConcept
WHERE O.OBJECT_TYPE = 'BIO01'
AND O.Meta_IsCurrent = 1
AND A.Meta_IsCurrent = 1
AND PL.Meta_IsCurrent = 1
表格值函数:
CREATE FUNCTION [Staging].[ufnGetCodeDescription]
(
@ProductLineId as nvarchar(20),
@ProductLineVersion as decimal(10,4),
@TariffTypeListVer as decimal(10,4),
@Type as nvarchar(20),
@Code as nvarchar(20)
)
RETURNS @returntable TABLE
(
CodeDescription nvarchar(100) NOT NULL,
Record_Timestamp datetime2 NOT NULL
)
AS
BEGIN
DECLARE @CodeDescription as nvarchar(200)
DECLARE @Record_Timestamp as datetime2
SELECT
@CodeDescription = X.[Description],
@Record_Timestamp = X.RECORD_TIMESTAMP
FROM [Archive].[TIA_TIA_TARIFF_STRUCTURE] TS
INNER JOIN [Archive].[TIA_TIA_TARIFF_CODES] TC
ON TC.PRODUCT_LINE_ID = @ProductLineId AND TC.[TYPE] = TS.[TYPE] AND TC.[VERSION] = TS.TYPE_VERSION
INNER JOIN [Archive].[TIA_TIA_XLA_PE_REFERENCE] X
ON TC.[TYPE] = X.Table_Name AND @ProductLineId = X.ID AND TC.[VERSION] = X.[VERSION] AND TC.CODE = X.[CODE]
WHERE
TS.PRODUCT_LINE_ID = @ProductLineId
AND
TS.[VERSION] = @TariffTypeListVer
AND TS.CLASS = 'CODE'
AND TC.[TYPE] = @Type
AND TC.Code = @Code
AND X.[Language] = 'DK'
AND TS.Meta_IsCurrent = 1
AND TC.Meta_IsCurrent = 1
AND X.Meta_IsCurrent = 1
IF @CodeDescription IS NOT NULL AND @Record_Timestamp IS NOT NULL
BEGIN
INSERT @returntable
SELECT @CodeDescription, @Record_Timestamp
END;
RETURN;
END
执行计划原始查询:
执行计划新查询:
答案 0 :(得分:2)
使用OUTER APPLY实际上为每一行执行函数(以及函数中的SELECT)。
相反,我建议将函数调用移出FROM / WHERE。只需检索所有必要的列/
我们的想法是首先选择必要的列,并将函数调用到相对较小的行集,其中所有过滤器都已应用。
SELECT
sub.*,
carConcept.*
FROM (the new query except the OUTER APPLY) sub
OUTER APPLY Staging.ufnGetCodeDescription(SUB.PRODUCT_LINE_ID, SUB.PRODUCT_LINE_VER_NO, SUB.TARIFF_TYPE_LIST_VER,
CASE WHEN SUB.C52 IS NOT NULL
THEN 'XTARIFTYPE'
ELSE 'ART'
END,
CASE WHEN SUB.C52 IS NOT NULL
THEN SUB.C52
ELSE SUB.C02
END) carConcept
或者您仍然可以使用INNER JOIN。如果INNER JOIN返回多行,则添加GROUP BY逻辑以返回第一个值。
答案 1 :(得分:0)
我在函数中加入的表(TIA_TIA_TARIFF_STRUCTURE,TIA_TIA_TARIFF_CODES,TIA_TIA_XLA_PE_REFERENCE)没有正确的索引。
我认为没有必要,因为它们包含大约3K,17K和22K行。
将聚集索引放在[Staging]。[ufnGetCodeDescription]的表中,将性能从30秒加到5-6秒。