如何解决合并带有视图的语句
我有一个如下的合并语句,
MERGE INTO test a
USING @temptable b ON a.[col1] = b.[col1]
WHEN MATCHED THEN
UPDATE
SET a.[col2] = b.[col2],a.[col3] = b.[col3],a.[col4] = b.[col4],a.[col5] = b.[col5]
WHEN NOT MATCHED THEN
INSERT VALUES(b.[col1],b.[col2],b.[col3],b.[col4],b.[col5]);
一个表和如下表类型结构({col1
已被非聚簇索引)
CREATE TYPE [dbo].[test] AS TABLE
(
[col1] [int] NULL,[col2] [varchar](100) NULL,[col3] [varchar](100) NULL,[col4] [varchar](100) NULL,[col5] [varchar](100) NULL
)
我要解决的问题是,当目标表变大时,合并需要花费更多时间。在我的情况下,一批将有90%的插入和10%的更新。因此,我尝试通过使用像[col1] > 500000
这样的条件来使用视图进行合并。
根据我的测试,将相同的50000条记录向上插入50次到总记录为8084328行的表中,速度从35092ms增加到23336ms。
这是处理大型表合并的正确方法吗?
解决方法
数据设置
我正在使用糟糕的数据设置进行一些测试,以了解SQL Server的功能。不同设置的主要区别在于
- 排序数据
- 减少读取次数
我发现最重要的是
- 使用表变量(例如
@temptable
)通常会导致内存授予不足,因为它只需要一行。然后溢出到磁盘,使其变慢。临时表#temptable
通常效果更好。 - 对于原始表
test
,当col1
上只有一个非聚集索引时,它工作得最好。本质上,出于合并的目的,我们只关心行是否存在,现在是col2到col5是什么。
我发现对速度没用的
- 在优良做法imo中,向
test
添加主键(或聚集索引)会降低速度,因为插入需要更新相关的聚集索引。如果要插入聚簇索引的中间,则比添加到结尾要花更多时间。 - 对于保存数据的临时表
#temptable
,它在没有任何其他特定索引的情况下通常工作得比较好。在某些情况下,添加聚集索引(例如CREATE CLUSTERED INDEX #CX_temptable ON #temptable (col1,col2,col3,col4,col5);
)会带来较小的速度改进,并且其他时间引起更多阅读。
常规方法
这个问题的一部分,您担心什么?如果整个过程花了一秒钟(但是在那一秒内将其他所有内容都锁定了),这是不好的吗?如果主要目的是使锁尽可能短,那么可以考虑使用其他方法。
其他选项包括
- 分批处理,例如一次合并10,000个案例。这样可以最大程度地缩短“锁定”时间段,但可以连续多次执行。如果您在服务器上的内存可用性不佳并且合并所需的内存比您的多,这也可能很有用。但是,最终它将使用更多的总处理能力,如果有人在中间使用它,他们可能会得到仅部分更新的数据。
- 将其与分别执行
update
和insert
的命令进行比较。这些中的每一个都可能比合并更短并且使用更少的内存,并且总处理时间可能会更长一些……但是根据您可用的资源,它实际上可能会更快。如果总体上这样快,您也可以将两者包装到一个事务中,以阻止所有用户看到部分更新的数据。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。