如何减少并发 DELETE & INSERT 到 SQL 服务器中的单个 table 期间的阻塞
How to reduce blocking during concurrent DELETE & INSERT to a single table in SQL Server
我们有一个存储过程,可以加载有关订单的详细信息。我们总是想要有关订单的最新信息,因此每次调用存储过程时都会重新生成订单的订单详细信息。我们正在使用 SQL Server 2016。
伪代码:
- 根据订单标识符按聚簇索引删除
- INSERT 到 table,基于包含订单信息的巨大查询
当多个最终用户同时执行存储过程时,会在 orderdetails
table 上创建阻塞。一旦第一个呼叫者完成,第二个呼叫者排队,然后是第三个呼叫者。因此,orderdetails
的生成时间随着时间的推移而增加。这种情况尤其发生在包含 > 100k 或 1 或 200 万的详细信息行的大订单的情况下,因为正在发生 table 级锁定。
我们采用的方法
我们根据并发 orderdetails
加载的订单标识符的最后一位数字对 table 进行了分区。这提高了第一次 orderdetails
加载时的性能,因为没有删除。但是,从第二次开始,第一个会话中的 INSERT
导致其他会话 DELETE
阻塞。其他会话被阻止,直到第一个会话完成 INSERT
.
我们正在考虑为每个订单创建单独的 orderdetails
table 以避免此并发问题。
问题
能否请您提出一些支持并发 DELETE
和 INSERT
场景的方法?
我们通过为 orderdetails
临时 table 解决了争用问题。我们发现巨大的查询花费了更长的 SELECT 时间,而这个更长的时间导致 orderdetails
[=31= 上更长的 table 级别锁定].
因此,我们首先将数据加载到临时 table #orderdetail
中,然后在 orderdetail
table 中进行 DELETE 和 INSERT。
由于 orderdetail
table 已经分区,DELETE 速度更快并且 INSERT 并行发生. INSERT 在这里也非常快,因为它很简单 table 从 #orderdetail
table 扫描。
你可以给Hekaton Engine看看。如果您使用 SP1
,它甚至可以在 SQL Server Standard Edition
中使用。
如果由于硬件或软件的限制实现起来太复杂,你可以尝试玩玩数据库的Isolation Levels。有时,读取大量数据的查询会被阻塞,甚至是修改部分数据的查询的死锁受害者。你可以问问自己,你是否需要保证用户读取的数据是有效的,或者你可以承受例如一些脏读?
我们有一个存储过程,可以加载有关订单的详细信息。我们总是想要有关订单的最新信息,因此每次调用存储过程时都会重新生成订单的订单详细信息。我们正在使用 SQL Server 2016。
伪代码:
- 根据订单标识符按聚簇索引删除
- INSERT 到 table,基于包含订单信息的巨大查询
当多个最终用户同时执行存储过程时,会在 orderdetails
table 上创建阻塞。一旦第一个呼叫者完成,第二个呼叫者排队,然后是第三个呼叫者。因此,orderdetails
的生成时间随着时间的推移而增加。这种情况尤其发生在包含 > 100k 或 1 或 200 万的详细信息行的大订单的情况下,因为正在发生 table 级锁定。
我们采用的方法
我们根据并发 orderdetails
加载的订单标识符的最后一位数字对 table 进行了分区。这提高了第一次 orderdetails
加载时的性能,因为没有删除。但是,从第二次开始,第一个会话中的 INSERT
导致其他会话 DELETE
阻塞。其他会话被阻止,直到第一个会话完成 INSERT
.
我们正在考虑为每个订单创建单独的 orderdetails
table 以避免此并发问题。
问题
能否请您提出一些支持并发 DELETE
和 INSERT
场景的方法?
我们通过为 orderdetails
临时 table 解决了争用问题。我们发现巨大的查询花费了更长的 SELECT 时间,而这个更长的时间导致 orderdetails
[=31= 上更长的 table 级别锁定].
因此,我们首先将数据加载到临时 table #orderdetail
中,然后在 orderdetail
table 中进行 DELETE 和 INSERT。
由于 orderdetail
table 已经分区,DELETE 速度更快并且 INSERT 并行发生. INSERT 在这里也非常快,因为它很简单 table 从 #orderdetail
table 扫描。
你可以给Hekaton Engine看看。如果您使用 SP1
,它甚至可以在 SQL Server Standard Edition
中使用。
如果由于硬件或软件的限制实现起来太复杂,你可以尝试玩玩数据库的Isolation Levels。有时,读取大量数据的查询会被阻塞,甚至是修改部分数据的查询的死锁受害者。你可以问问自己,你是否需要保证用户读取的数据是有效的,或者你可以承受例如一些脏读?