如何加快此SQL更新查询?

时间:2017-12-02 13:25:58

标签: sql sql-server performance query-optimization rows

A表是巨大的(50多万行)表。所以这个更新方法对于MSSQL服务器来说太慢了。除了它在商店程序的while循环中运行。我认为这个解决方案并不十分有效 有人有什么好主意来解决这个问题吗? 谢谢!

表格的定义

CREATE TABLE [dbo].[A](
    [E_NUM] [int] NOT NULL,
    [ID] [char](1) NOT NULL,
    [NUM] [int] NOT NULL,
    [h_out] [smallint] NOT NULL,
    [TAG] [smallint] NOT NULL,
    [TAG1] [smallint] NOT NULL,

 CONSTRAINT [PK_A] PRIMARY KEY CLUSTERED 
(
    [E_NUM] ASC,
    [ID] ASC,
    [NUM] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

B表的定义

CREATE TABLE [dbo].[B](
    [NUM] [int] NOT NULL,
    [NUM2] [int] NOT NULL,
    [TYPE] [char](1) NOT NULL,
    [R_DATE] [datetime] NULL,
    [Note] [varchar](100) NULL,
 CONSTRAINT [PK_B] PRIMARY KEY CLUSTERED 
(
    [NUM] ASC,
    [NUM2] ASC,
    [TYPE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] 

更新

 UPDATE A_1 
 SET A_1.TAG1 = -1
 FROM A
 INNER JOIN B ON A.NUM = B.NUM
 INNER JOIN A AS A_1 ON B.NUM2 = A_1.NUM 
 WHERE A.TAG1 = -1 AND A.TAG = -1 AND B.TYPE='X'
 AND  A.E_num = A_1.E_num AND A.ID=A_1.[ID];

2 个答案:

答案 0 :(得分:0)

MS SQL Server中的主键(默认情况下为PK)具有非常高的性能(与Oracle相比)。所以使用正确的PK并避免更新它们很重要。

当连接表时,最好定位一个表并通过where子句缩小它,然后使用PK来到达其他表中的记录。您可以使用执行计划找出MS SQL Server选择(目标)的表。

我认为您必须在表A中的TAG和TAG1列上声明一个组合索引以定位表A.如果A.TAG1 = -1 AND A.TAG = -1条件正确缩小表A,例如低于10000行具有此值。

答案 1 :(得分:0)

假设我没有犯任何错误,这应该等同于您的UPDATE语句:

 UPDATE upd 
    SET upd.TAG1 = -1
   FROM A upd

   JOIN A 
     ON A.ID    = upd.ID
    AND A.E_NUM = upd.E_NUM
    AND A.TAG1 = -1 
    AND A.TAG  = -1 

   JOIN B 
     ON B.NUM  = A.NUM
    AND B.NUM2 = upd.NUM
    AND B.TYPE = 'X'

由于您没有B.TYPEA.TAG之类的任何索引,因此系统非常有必要遍历整个表以查找适用的记录。如果你的桌子很大,那么是的,这需要一些时间。

添加这些索引,然后重试:

CREATE INDEX idx1_A ON A (TAG, TAG1, ID, E_NUM) INCLUDE (NUM) -- NUM is implicit due to PK if you think about it
CREATE INDEX idx1_B ON B (TYPE, NUM, NUM2)

您可以认为更新TAG1也需要更新idx1_A,但这仍然比扫描整个表格快得多。 (**)

您可能想要添加

  WHERE upd.TAG1 <> -1 

以避免在已经存在正确值时进行更新,以最大限度地减少影响。

(**:如果您的更新影响了80%的记录,那么可能不值得在表A上使用索引,但请记住,这将是一个巨大的操作,因此需要很多时间,因为这是很多工作!)