在更新期间从表中选择

时间:2014-01-16 16:22:08

标签: sql sql-server-2008 select locking sql-update

我有一个表正在更新,更新本身需要8秒才能完成。当用户进来时,我需要更新表格并使用表格中的总和来显示它们:

查询

SELECT Jaccard/(SELECT SUM(Jaccard) FROM PreProcessed)
FROM PreProcessed
WHERE MinX = 25 AND MinY = 25
AND MaxX = 26 AND MaxY = 26

问题是多个用户可以同时进入,X语句的UPDATE锁定意味着我无法长时间从表中读取。

我想知道在更新发生时,我应该使用什么类型的LOCK来允许查询能够从先前提交的数据中SELECT进行查询?我最初想过使用READCOMMITTED,但它似乎没有做我想要的。我想要更新前的数据,而不是部分提交的数据。

存储过程

set statistics time ON

DECLARE @MinX INT = 0;
DECLARE @MinY INT = 0;
DECLARE @MaxX INT = 50;
DECLARE @MaxY INT = 50;

DECLARE @Lambda DECIMAL(10, 5) = 0.5;
DECLARE @ReverseLambda DECIMAL(10, 5) = 1 - @Lambda;

DECLARE @Area INT = (@MaxX - @MinX) * (@MaxY - @MinY);

UPDATE PreProcessed
SET Jaccard = (@ReverseLambda * Jaccard) + (@Lambda * dbo.fn_ComputeJaccard(@MinX, @MinY, @MaxX, @MaxY, @Area, MinX, MinY, MaxX, MaxY))
FROM PreProcessed

set statistics time off

如果有的话,我可以做些什么来允许读取更新?

修改

select CAST(1 AS DECIMAL(38, 28))/CAST(1625625 AS DECIMAL(38, 28))

select CAST(1 AS DECIMAL(20, 10))/CAST(1625625 AS DECIMAL(20, 10))

1 个答案:

答案 0 :(得分:1)

这是您需要进行反规范化的时间之一。创建一个表

create table PreProcessedTotal (
   JaccardTotal decimal(18, 4) not null
)

(替换适当的数据类型)。您需要向表PreProcessed添加三个触发器:

  • 用于在新行中添加Jaccard值的插入触发器
  • 更新,添加插入的值并减去DELETED
  • 删除触发器以减去已删除的值

然后您可以使用:

select Jaccard / JaccardTotal
from Preprocessed with (nolock)
cross join PreProcessedTotal with (nolock)

可能不需要with (nolock)。当你把它放到现场时,你还需要用当前总数填充PreProcessedTotal表。