【问题标题】:Updating 980K records efficiently where row has a max value in a group有效更新 980K 记录,其中行在组中具有最大值
【发布时间】:2019-07-05 21:40:53
【问题描述】:

我正在努力在合理的时间内更新数据库中的 980,000 条记录。

我必须在 PriceID 等于组的最大值(按 ProductID 分组)的行中将 NextLp 的值设置为“NULL”。

为了形象化,这是我的例子:

+-----------+---------+--------+--------------- ------+
|产品编号 |价格ID |下一张 |将 NextLp 设置为 NULL? |
+-----------+---------+--------+------------------ ---+
|苹果 | 1 | - | |
+-----------+---------+--------+------------------ ---+
|苹果 | 2 | - | |
+-----------+---------+--------+------------------ ---+
|苹果 | 3 | - |是 |
+-----------+---------+--------+------------------ ---+
|梨 | 1 | - | |
+-----------+---------+--------+------------------ ---+
|梨 | 2 | - |是 |
+-----------+---------+--------+------------------ ---+

我尝试了各种方法,但所有这些方法都至少需要 15 秒才能更新 100 条记录。还有 979,100 条记录要做 - 所以我的方法绝对不可行。

感谢您的帮助。

版本为 MS SQL 2016

【问题讨论】:

  • 你有触发器吗?你在同一张表上有并发查询吗?您的数据库是否处于完全恢复模式?您在查询的列上有索引?请尽可能多地添加信息,包括实际的更新声明。
  • @EzLo 无法回答。服务器相当远程,我只能通过可以运行查询的控制台访问。尽管如此,对相同数量记录的其他更新查询运行时间不到 50 秒。

标签: sql-server performance tsql sql-server-2016


【解决方案1】:

也许这有什么?

DECLARE @tbl TABLE(ProductID VARCHAR(100),PriceID INT,NextLp VARCHAR(100));
INSERT INTO @tbl VALUES
 ('APPLE',1,'-')
,('APPLE',2,'-')
,('APPLE',3,'-')
,('PEAR ',1,'-')
,('PEAR ',2,'-');

WITH UpdatableCTE AS
(
    SELECT * 
          ,ROW_NUMBER() OVER(PARTITION BY ProductID ORDER BY PriceID DESC) AS Nr
    FROM @tbl 
)
UPDATE UpdatableCTE SET NextLp=NULL
WHERE Nr=1;

SELECT * FROM @tbl;

您可以先使用可更新的 CTE 将数字放入您的行,然后再更新您的目标。

更新

结果

ProductID   PriceID NextLp
APPLE       1       -
APPLE       2       -
APPLE       3       NULL
PEAR        1       -
PEAR        2       NULL

在我上面的示例中,两行设置为NULL。这两行都是其组中最高的 PriceID...

ROW_NUMBER()a window functionOVER()-clause 允许PARTITION BY 在集合内创建组,而ORDER BY 将对组进行排序,在这种情况下按PriceID 降序排列。这会将1 绑定到每一行,其中PriceIDProductID 组中的最高值。

提示:您可以使用SELECT * FROM UpdatableCTE 代替UPDATE 语句。这将显示编号的行并允许检查编号。

【讨论】:

  • 这似乎根本没有改变 NextLp。将 ORDER BY 更改为 ProductID 并将 PARTITION BY 更改为 PriceID 会将所有 NextLp 设置为 NULL。
  • @JCode 抱歉,可能是我搞错了...查看我的更新
  • 我的错,我没有想到执行 SELECT TOP(100) 可能不会在数据库中产生所有结果,结果隐藏了带有 NULL 的结果。非常感谢您,先生,祝您有美好的一天。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多