SQL服务器如何正确地创建依赖表的视图?
SQL Server How to properly create a view upon dependent tables?
鉴于以下 tables(见下文),我需要创建一个视图来显示来自 table MedDRARelations
的每个代码(SOC、HLGT、HLT、PT 和 LLT)以及来自 table MedDRANames
.
我试过多次加入 MedDRANames
table 并创建一个标量函数,给定代码(键)returns 值。
Table 定义:
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
我想知道实现此目的的正确方法是什么,因为创建连接的 table 耗时 12.2 秒(SD 0.1),但成本是原始 space 的 5 倍。
提前致谢。
更新:执行计划
- 使用函数:https://www.brentozar.com/pastetheplan/?id=rkso0aKnV
- 在 Ixs 创作之前:https://www.brentozar.com/pastetheplan/?id=HkFlyRth4
- 在 Ixs 创作之后(如 Laughing Vergil 所建议):https://www.brentozar.com/pastetheplan/?id=B13ZW0t3V
第一种方法是正确的。 INNER JOIN
s 在单列整数主键上非常快,通常通过 MERGE JOIN
运算符执行。正如您的结果所显示的那样,肯定比创建函数更快。
这里最大的问题是 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);
然后再次尝试您的视图和其他方法。
鉴于以下 tables(见下文),我需要创建一个视图来显示来自 table MedDRARelations
的每个代码(SOC、HLGT、HLT、PT 和 LLT)以及来自 table MedDRANames
.
我试过多次加入 MedDRANames
table 并创建一个标量函数,给定代码(键)returns 值。
Table 定义:
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
我想知道实现此目的的正确方法是什么,因为创建连接的 table 耗时 12.2 秒(SD 0.1),但成本是原始 space 的 5 倍。
提前致谢。
更新:执行计划
- 使用函数:https://www.brentozar.com/pastetheplan/?id=rkso0aKnV
- 在 Ixs 创作之前:https://www.brentozar.com/pastetheplan/?id=HkFlyRth4
- 在 Ixs 创作之后(如 Laughing Vergil 所建议):https://www.brentozar.com/pastetheplan/?id=B13ZW0t3V
第一种方法是正确的。 INNER JOIN
s 在单列整数主键上非常快,通常通过 MERGE JOIN
运算符执行。正如您的结果所显示的那样,肯定比创建函数更快。
这里最大的问题是 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);
然后再次尝试您的视图和其他方法。