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];
答案 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.TYPE
或A.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上使用索引,但请记住,这将是一个巨大的操作,因此需要很多时间,因为这是很多工作!)