加快视图性能
Speed up view performance
我有一个旧视图需要 4 分钟才能完成 运行,我被要求加快速度。 FROM 看起来像这样:
FROM TableA
CROSS JOIN ViewA
INNER JOIN TableB on ViewA.Name = TableB.Name
AND TableA.Code = TableB.Code
AND TableA.Location = TableB.Location
WHERE (DATEDIFF(m, ViewA.SubmitDate, GETDATE()) = 1) -- Only pull last months rows
Table A 大约有 99k 行,ViewA 大约有 2000 行,TableB 大约有 101K 行。我认为问题出在 INNER JOIN 上,因为我删除了它,查询需要 1 秒。
我的第一个想法是看看我是否可以通过将整个事物分解为 CTE 来减少 ViewA 中的行数,但这产生了零影响。我想我需要索引 TableB,因为它只是在连接中使用的一堆 varchars。我现在将其更改为 temp tables 以便我可以对其进行索引。我无法更改基础 table 和视图。 index temp table 是个好方法,还是有更好的解决方案。
编辑以添加有关现有索引的信息。现在唯一带有索引的是 TableA.Id,它是 PK 和聚集索引。 TableB 有一个 Id 字段,但它不是 PK。 ViewA 未编入索引。
再次编辑以更正一些结构。 SubmitDate 在视图中,而不是 table。
这是一个非常基本的结构:
CREATE TABLE TableA
(
Id int NOT NULL PRIMARY KEY,
Section varchar(20) NULL,
Code varchar(20) NULL
)
CREATE TABLE TableB
(
Id int NOT NULL PRIMARY KEY,
Name varchar(20) NULL,
Code varchar(20) NULL,
Section varchar(20) NULL
)
CREATE TABLE TableC
(
Id int NOT NULL PRIMARY KEY,
Name varchar(20) NULL,
SubmitDate DateTime NOT NULL
)
CREATE TABLE TableD
(
Id int NOT NULL PRIMARY KEY,
Section varchar(20) NULL
)
CREATE VIEW ViewA
AS
SELECT c.Section, d.Name, c.SubmitDate
FROM TableC c
JOIN TableD d ON a.Id = b.Id
一个改进是将 where 子句重写为 sargable 子句。如果没有索引,则将索引添加到 SubmitDate
并将查询更改为:
FROM TableA
CROSS JOIN ViewA
INNER JOIN TableB on ViewA.Name = TableB.Name
AND TableA.Code = TableB.Code
AND TableA.Location = TableB.Location
WHERE
TableA.SubmitDate >=DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())-1,0)
And TableA.SubmitDate < Dateadd(DAY, 1, DATEADD(MONTH,
DATEDIFF(MONTH, -1, GETDATE())-1, -1) )
还在 Name
、Code
和 Location
列上添加非聚集索引。
我有一个旧视图需要 4 分钟才能完成 运行,我被要求加快速度。 FROM 看起来像这样:
FROM TableA
CROSS JOIN ViewA
INNER JOIN TableB on ViewA.Name = TableB.Name
AND TableA.Code = TableB.Code
AND TableA.Location = TableB.Location
WHERE (DATEDIFF(m, ViewA.SubmitDate, GETDATE()) = 1) -- Only pull last months rows
Table A 大约有 99k 行,ViewA 大约有 2000 行,TableB 大约有 101K 行。我认为问题出在 INNER JOIN 上,因为我删除了它,查询需要 1 秒。
我的第一个想法是看看我是否可以通过将整个事物分解为 CTE 来减少 ViewA 中的行数,但这产生了零影响。我想我需要索引 TableB,因为它只是在连接中使用的一堆 varchars。我现在将其更改为 temp tables 以便我可以对其进行索引。我无法更改基础 table 和视图。 index temp table 是个好方法,还是有更好的解决方案。
编辑以添加有关现有索引的信息。现在唯一带有索引的是 TableA.Id,它是 PK 和聚集索引。 TableB 有一个 Id 字段,但它不是 PK。 ViewA 未编入索引。
再次编辑以更正一些结构。 SubmitDate 在视图中,而不是 table。
这是一个非常基本的结构:
CREATE TABLE TableA
(
Id int NOT NULL PRIMARY KEY,
Section varchar(20) NULL,
Code varchar(20) NULL
)
CREATE TABLE TableB
(
Id int NOT NULL PRIMARY KEY,
Name varchar(20) NULL,
Code varchar(20) NULL,
Section varchar(20) NULL
)
CREATE TABLE TableC
(
Id int NOT NULL PRIMARY KEY,
Name varchar(20) NULL,
SubmitDate DateTime NOT NULL
)
CREATE TABLE TableD
(
Id int NOT NULL PRIMARY KEY,
Section varchar(20) NULL
)
CREATE VIEW ViewA
AS
SELECT c.Section, d.Name, c.SubmitDate
FROM TableC c
JOIN TableD d ON a.Id = b.Id
一个改进是将 where 子句重写为 sargable 子句。如果没有索引,则将索引添加到 SubmitDate
并将查询更改为:
FROM TableA
CROSS JOIN ViewA
INNER JOIN TableB on ViewA.Name = TableB.Name
AND TableA.Code = TableB.Code
AND TableA.Location = TableB.Location
WHERE
TableA.SubmitDate >=DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())-1,0)
And TableA.SubmitDate < Dateadd(DAY, 1, DATEADD(MONTH,
DATEDIFF(MONTH, -1, GETDATE())-1, -1) )
还在 Name
、Code
和 Location
列上添加非聚集索引。