【问题标题】:SQL Server How to properly create a view upon dependent tables?SQL Server 如何根据依赖表正确创建视图?
【发布时间】:2019-05-15 16:01:41
【问题描述】:

鉴于下表(见下文),我需要创建一个视图,显示表 MedDRARelations 中的每个代码(SOC、HLGT、HLT、PT 和 LLT)及其各自的值(Soc_Value、HLGT_value、HLT_Value、PT_Value 和LLT_Value) 来自表 MedDRANames

我尝试多次加入MedDRANames 表并创建一个标量函数,该函数返回给定代码(键)的值。

表定义:

CREATE TABLE dbo.MedDRANames 
(
    [Key]   INT NOT NULL,
    [Value] VARCHAR(100) NULL,
    CONSTRAINT [PK_MedDRANames] PRIMARY KEY CLUSTERED ([Key])
);

CREATE TABLE dbo.MedDRARelations 
(
    [SOC]  INT NOT NULL,
    [HLGT] INT NOT NULL,
    [HLT]  INT NOT NULL,
    [PT]   INT NOT NULL,
    [LLT]  INT NOT NULL,    
    CONSTRAINT [PK_MedDRARelations] 
        PRIMARY KEY CLUSTERED ([SOC] ASC, [HLGT] ASC, [HLT] ASC, [PT] ASC, [LLT] ASC),
    CONSTRAINT [FK_MedDRANameSOC] 
        FOREIGN KEY ([SOC]) REFERENCES dbo.MedDRANAmes([Key]),
    CONSTRAINT [FK_MedDRANameHLGT] 
        FOREIGN KEY ([HLGT]) REFERENCES dbo.MedDRANAmes([Key]),
    CONSTRAINT [FK_MedDRANameHLT] 
        FOREIGN KEY ([HLT]) REFERENCES dbo.MedDRANAmes([Key]),
    CONSTRAINT [FK_MedDRANamePT] 
        FOREIGN KEY ([PT]) REFERENCES dbo.MedDRANAmes([Key]),
    CONSTRAINT [FK_MedDRANameLLT] 
        FOREIGN KEY ([LLT]) REFERENCES dbo.MedDRANAmes([Key])
);

观看次数:

此视图在 22.1 秒 (SD 1.25) 内执行并影响 156867 行

SELECT 
    [X].[SOC] AS [Código SOC],
    [SOC].[Value] AS [Término SOC],
    [X].[HLGT] AS [Código HLGT],
    [HLGT].[Value] AS [Término HLGT],
    [X].[HLT] AS [Código HLT],
    [HLT].[Value] AS [Término HLT],
    [X].[PT] AS [Código PT],
    [PT].[Value] AS [Término PT],
    [X].[LLT] AS [Código LLT],
    [LLT].[Value] AS [Término LLT]
FROM 
    dbo.MedDRARelations AS [X]
INNER JOIN 
    dbo.MedDRANames AS [SOC] ON [X].[SOC] = [SOC].[Key]
INNER JOIN 
    dbo.MedDRANames AS [HLGT] ON [X].[HLGT] = [HLGT].[Key]
INNER JOIN 
    dbo.MedDRANames AS [HLT] ON [X].[HLT] = [HLT].[Key]
INNER JOIN 
    dbo.MedDRANames AS [PT] ON [X].[PT] = [PT].[Key]
INNER JOIN 
    dbo.MedDRANames AS [LLT] ON [X].[LLT] = [LLT].[Key]

此视图在 35.3 秒 (SD 2.1) 内执行并影响 156867 行

SELECT 
    [X].[SOC] AS [Código SOC],
    dbo.FindMedDRA(x.SOC) AS [Término SOC],
    [X].[HLGT] AS [Código HLGT],
    dbo.FindMedDRA(x.HLGT) AS [Término HLGT],
    [X].[HLT] AS [Código HLT],
    dbo.FindMedDRA(x.HLT) AS [Término HLT],
    [X].[PT] AS [Código PT],
    dbo.FindMedDRA(x.PT) AS [Término PT],
    [X].[LLT] AS [Código LLT],
    dbo.FindMedDRA(x.LLT) AS [Término LLT]
FROM 
    dbo.MedDRARelations AS [X]

标量函数:

CREATE FUNCTION [dbo].[FindMedDRA]
    (@code INT)
RETURNS VARCHAR(100)
AS
BEGIN
    DECLARE @returning VARCHAR(100)

    SELECT @returning = dbo.MedDRANames.Value 
    FROM dbo.MedDRANames 
    WHERE dbo.MedDRANames.[Key] = @code

    RETURN @returning
END

我想知道实现此目的的正确方法是什么,因为创建连接表需要 12.2 秒 (SD 0.1) 但成本是原始空间的 5 倍。

提前致谢。

更新:执行计划

  1. 使用函数:https://www.brentozar.com/pastetheplan/?id=rkso0aKnV
  2. 在 Ixs 创作之前:https://www.brentozar.com/pastetheplan/?id=HkFlyRth4
  3. 在 Ixs 创作之后(由 Laughing Vergil 建议):https://www.brentozar.com/pastetheplan/?id=B13ZW0t3V

【问题讨论】:

  • 您是否担心代码长度?在尝试以正确的方式实现时,这并不重要。 MedDRANames 的每个实例代表一个不同的实体,应该独立调用。使用用户定义的标量函数是一个性能问题,应尽可能避免。
  • 可以分享一下执行计划吗?转到brentozar.com/pastetheplan并粘贴执行计划的XML版本
  • @LaughingVergil 使用 UDF 时执行计划不会显示准确的成本。
  • 是的,但是当你只显示视图版本时它会,没有这个功能。
  • 您不能执行视图 - 您可以通过定义视图的表和连接来创建视图,然后从视图中选择。你是这个意思吗?从视图中选择所有行需要 22.1 vs 35.3 秒....

标签: sql sql-server database-performance sqlperformance


【解决方案1】:

这里最大的问题是MedRARelations 中的值没有索引。注意:一个常见的误解是创建外键会创建索引。它没有。

所以,试试运行这个:

CREATE INDEX Idx_MedDRARelations_SOC ON MedDRARelations (SOC);
CREATE INDEX Idx_MedDRARelations_HGLT ON MedDRARelations (HGLT);
CREATE INDEX Idx_MedDRARelations_HLT ON MedDRARelations (HLT);
CREATE INDEX Idx_MedDRARelations_PT ON MedDRARelations (PT);
CREATE INDEX Idx_MedDRARelations_LLT ON MedDRARelations (LLT);

然后再次尝试您的视图和其他方法。

【讨论】:

  • 由于表MedDRARelations只被调用一次,所以只能使用一个索引。而且由于没有 WHERE 子句,它很可能会进行表/聚集索引扫描。
【解决方案2】:

第一种方法是正确的。单列整数主键上的INNER JOINs 非常快,通常通过MERGE JOIN 运算符执行。正如您的结果所表明的那样,肯定比创建函数要快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    相关资源
    最近更新 更多