首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >优化缓慢的T存储过程

优化缓慢的T存储过程
EN

Stack Overflow用户
提问于 2015-07-17 14:49:59
回答 4查看 112关注 0票数 1

我正在为我的数据库中的一个表创建一个存储过程;但是,由于必须执行大量的联接,它运行得非常慢。我正在尝试一种优化查询的方法,这样我就不需要执行那么多的左联接了,但是我很难找到这样的方法。我的代码如下所示:

代码语言:javascript
运行
复制
ALTER PROCEDURE [dbo].[STS]
AS
DECLARE @t0 table(Id nvarchar(7), Date1 date, TIV float, [1mo] float, RAN nvarchar(50), SAN nvarchar(50))
INSERT INTO @t0(Id, Date1, TIV, [1mo], RAN, SAN)
SELECT Id, Date1, TIV, TMR, RAN, SAN
FROM dbo.History
WHERE (Date1 IS NOT NULL) AND (Valid IS NULL OR Valid <> 0) AND (include <> 0)

DECLARE @t1 table(Id nvarchar(7), Date1 date, TIV float, [3mo] float, RAN nvarchar(50), SAN nvarchar(50))
INSERT INTO @t1(Id, Date1, TIV, [3mo], RAN, SAN) 
SELECT * FROM dbo.Series(3)

DECLARE @t2 table(Id nvarchar(7), Date1 date, TIV float, [6mo] float, RAN nvarchar(50), SAN nvarchar(50))
INSERT INTO @t2(Id, Date1, TIV, [6mo], RAN, SAN) 
SELECT * FROM dbo.Series(6)

DECLARE @t3 table(Id nvarchar(7), Date1 date, TIV float, [9mo] float, RAN nvarchar(50), SAN nvarchar(50))
INSERT INTO @t3(Id, Date1, TIV, [9mo], RAN, SAN) 
SELECT * FROM dbo.Series(9)


 SELECT t0.*, Join2.[3mo], Join2.[6mo], Join2.[9mo]
 FROM @t0 as t0
 LEFT OUTER JOIN
     (SELECT t1.*, Join1.[6mo], Join1.[9mo]
     FROM @t1 as t1
     LEFT OUTER JOIN
         (SELECT t2.*, t3.[9mo]
         FROM @t2 as t2
         LEFT OUTER JOIN @t3 as t3 
         ON t2.Id = t3.Id AND t2.Date1 = t3.Date1 AND t2.RAN = t3.RAN AND 
             t2.SAN = t3.SAN) as Join1
     ON t1.Id = Join1.Id AND t1.Date1 = Join1.Date1 AND t1.RAN = Join1.RAN AND
             t1.SAN = Join1.SAN) as Join2
 ON t0.Id = Join2.Id AND t0.Date1 = Join2.Date1 AND t0.RAN = Join2.RAN AND
             t0.SAN = Join2.SAN

是否有一种简单的方法来优化这个缓慢的查询,或者我是否需要想一种新的方法来完成这个任务呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-07-17 15:15:04

尝试在最后一个联接的末尾添加选项(重新编译)

本文解释了许多关于表变量和临时表的内容:https://www.simple-talk.com/sql/t-sql-programming/temporary-tables-in-sql-server/

票数 1
EN

Stack Overflow用户

发布于 2015-07-17 15:00:36

表变量经常导致的问题是,由于没有统计数据,估计行数为1,这可能导致真正糟糕的连接性能。我建议的第一件事是尝试将它们更改为临时表。由于您没有提到有多少行,所以很难说这些临时表上是否有索引。桌子会有帮助,但这也是你可以尝试的东西。

如果查询仍然很慢,查看统计数据io输出以查看I/O计数和查询计划,看看会发生什么,应该有助于了解导致问题的原因。

票数 3
EN

Stack Overflow用户

发布于 2015-07-17 15:58:46

这看起来确实过于复杂,对于较大的数据集,表变量并不是很有效。

代码语言:javascript
运行
复制
   SELECT h.Id, h.Date1, h,TIV, h.[1mo], h.RAN, h.SAN, 
                threemonth.somefield as [3mo], sixmonth.somefield as[6mo],  ninemonth.somefield as[9mo]
    FROM dbo.History h
    LEFT OUTER JOIN dbo.Series(3) threemonth 
        ON h.Id = threemonth.Id AND h.Date1 =threemonth.Date1 
            AND h.RAN = threemonth.RAN AND   h.SAN = threemonth.SAN
    LEFT OUTER JOIN dbo.Series(6) sixmonth 
    ON sixmonth.Id = threemonth.Id AND sixmonth.Date1 =threemonth.Date1 
            AND sixmonth.RAN = threemonth.RAN AND  sixmonth.SAN = threemonth.SAN
    LEFT OUTER JOIN dbo.Series(9) ninemonth  
    ON sixmonth.Id = ninemonth.Id AND sixmonth.Date1 =ninemonth.Date1 
            AND sixmonth.RAN = ninemonth.RAN AND   sixmonth.SAN = ninemonth.SAN
    WHERE (h.Date1 IS NOT NULL) 
            AND (h.Valid IS NULL OR h.Valid <> 0) 
            AND (h.include <> 0)

现在它已经简化了,您可以更好地看到痛点。

首先,表函数将不为联接使用任何索引。因此,如果正在返回大量记录,则最好不要使用它。

而且,即使在使用索引时,正在连接的字段也不是很有效,因为您正在连接日期、变量以及ints。这可能需要重新设计您的表结构或表函数,以便为联接提供更好的东西。

如果不了解dbo.series()函数的作用,就很难提出具体的建议。但是,如果h.Id是唯一的(而且可能是PK),则可能没有必要执行所有其他连接条件。同样,这取决于表值函数中发生的功。我只是根据多年的数据库经验和数百个数据库的知识来猜测。如果你能以任何方式简单的连接,你会得到更好的性能。不过,请记住,在试图简化时,您需要检查每一步,以确保您仍然返回相同的结果。

最后,您遇到了Where子句的问题。这里的两个问题是OR条件,它通常可以被UNION替换,以获得更好的性能和<>条件。我认为改进<>问题的一种方法是填充一个用可接受值进行索引的临时表,然后使用该表。不过,只有在有数千种可能的值的情况下,您才可能看到性能的大幅提高。如果可能的值位于查找表中,则可以使用子句对0进行筛选。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31478615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档