如何减少并发DELETE期间的阻塞INSERT到SQL Server中的单个表

时间:2017-10-16 18:31:09

标签: sql-server stored-procedures concurrency sql-server-2016 database-partitioning

我们有一个存储过程,可以加载订单的订单详细信息。我们总是想要有关订单的最新信息,因此每次调用存储过程时都会重新生成订单的订单详细信息。我们正在使用SQL Server 2016.

伪代码:

  • 基于订单标识符的聚集索引删除
  • 根据包含订单信息
  • 的巨大查询,插入表格

当多个最终用户同时执行存储过程时,会在orderdetails表上创建阻塞。第一个调用者完成后,第二个调用者排队,然后是第三个调用者。因此,随着时间的推移,生成orderdetails的时间会增加。特别是在包含>中的详细信息行的大订单的情况下,会发生这种情况。 100k或1或200万,因为有桌面级锁定正在发生。

我们采取的方法

我们根据并发orderdetails加载的订单标识符的最后一位数对表进行了分区。这样可以提高第一次orderdetails加载时的性能,因为没有删除。但是,第二次,第一次会话中的INSERT会阻止其他会话DELETE。其他会话将被阻止,直到第一个会话完成INSERT

我们正在考虑为每个订单创建单独的orderdetails表,以避免出现这种并发问题。

问题

您能否提出一些方法,以支持并发DELETE& INSERT场景?

2 个答案:

答案 0 :(得分:2)

我们通过寻找orderdetails的临时表解决了争用问题。我们发现大量查询花费的时间更长 SELECT ,这个更长的时间导致orderdetails表上的表级锁更长。

因此,我们首先将数据加载到临时表#orderdetail中,然后在orderdetail表中进行DELETE和INSERT。

由于orderdetail表已经分区, DELETE 更快, INSERT 并行发生。 INSERT 在这里也非常快,因为它是来自#orderdetail表的简单表扫描。

答案 1 :(得分:1)

您可以查看Hekaton Engine。如果您使用SQL Server Standard Edition,它甚至可以在SP1中使用。

如果由于硬件或软件限制而导致实施过于复杂,您可以尝试使用数据库的Isolation Levels。有时,正在读取大量数据的查询被阻止,甚至是修改这些数据部分的查询的死锁受害者。您可以问自己,您是否需要保证用户读取的数据有效,或者您可以负担得起例如一些脏读?