加快视图性能

Posted

技术标签:

【中文标题】加快视图性能【英文标题】:Speed up view performance 【发布时间】:2015-04-23 22:27:49 【问题描述】:

我有一个需要 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

表 A 大约有 99k 行,ViewA 大约有 2000 行,TableB 大约有 101K 行。我认为问题出在 INNER JOIN 因为我删除它,查询需要 1 秒。

我的第一个想法是看看是否可以通过将整个内容分解为 CTE 来减少 ViewA 中的行数,但这会产生零影响。我想我需要索引 TableB,因为它只是在连接中使用的一堆 varchars。我现在将它更改为临时表,以便我可以索引它。我无法更改基础表和视图。索引临时表是一个好方法,还是有更好的解决方案。

编辑以添加有关现有索引的信息。现在唯一带有索引的是 TableA.Id,它是 PK 和聚集索引。 TableB 有一个 Id 字段,但它不是 PK。 ViewA 未编入索引。

再次编辑以更正某些结构。 SubmitDate 在视图中,而不是表中。

这是一个非常基本的结构:

    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

【问题讨论】:

为什么是CROSS JOINTableA.SubmitDate 上面有索引吗?即使没有,stop using non-sargable arguments against it(也可以是stop using shorthand),并尝试 >= 上月初和 (我展示了计算句点开头here 和here 的简单方法,而后者显示了一个错误,应该鼓励您停止在谓词中使用DATEDIFF。) 查看关于键和索引的编辑。 【参考方案1】:

一个改进是将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) )

还在NameCodeLocation 列上添加非聚集索引。

【讨论】:

当您说要为这些列添加索引时,我不是必须拥有对这些表的访问/权限吗? (我不)。或者有没有办法将临时索引作为查询的一部分? 抱歉,SubmitDate 在视图中,而不是在表格中。 那么有权限的人应该帮助你。您也可以在视图上创建索引,但有很多限制 无法对 submitdate 列进行索引,但对其他列进行了索引,并使 where 子句成为 sargable,现在在 5 秒内运行!谢谢!

以上是关于加快视图性能的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 视图 - 性能不佳

如何衡量布局性能?

加快 Gatsby 性能

如何加快 PostgreSQL 中的插入性能

如何加快选择框的性能?

SQL加快插入的性能?