我对以下查询有疑问
UPDATE P
set P.price = (select top 1 PV.price
from @port_values PV
where PV.pv_id < P.pv_id
and PV.price is not NULL
and PV.id = P.id
order by PV.pv_id desc)
FROM @port_values P
WHERE P.price is NULL
它正在做的是回顾历史以查找以前的任何先前的价格值,并将其应用于价格为NULL的地方。 pv_id
按日期顺序排列并建立索引。以前是按日期排序的,但性能没有变化。
它以合理的性能工作,但是数据库变得越来越大,这一行代码有效地挂起了查询。对于较小的数据集也可以,但是在@port_values具有约40万行的情况下。显然,它正在执行迭代表扫描,并且根本没有效率。我尝试过将索引放在具有任何性能的列上。
像这样构造查询的最有效方法是什么?
答案 0 :(得分:0)
由于您的环境不可用,我们无法提供确切的解决方案。但是请尝试下面的方法,让我知道它是否对性能有影响
方法1:
UPDATE P SET P.price = PV.price
FROM @port_values P
INNER JOIN
(
SELECT id, price FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY PV.id ORDER BY PV.pv_id ASC) AS SNO
,PV.id
,PV.price
FROM @port_values PV
WHERE PV.price is not NULL
)AS A
WHERE SNO= 1
)PV ON P.id = PV.ID
WHERE P.price is NULL
方法2:
CREATE TABLE #TAB (ID INT PRIMARY KEY, price DECIMAL(18,2))
INSERT INTO #TAB
SELECT id, price FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY PV.id ORDER BY PV.pv_id ASC) AS SNO
,PV.id
,PV.price
FROM @port_values PV
WHERE PV.price is not NULL
)AS A
WHERE SNO= 1
UPDATE P SET P.price = PV.price
FROM @port_values P
INNER JOIN #TAB PV ON P.id = PV.ID
WHERE P.price is NULL
答案 1 :(得分:0)
请尝试此非标准sql性能是否更好
UPDATE P
set P.price = s.price
FROM @port_values P
Outer apply(
select top 1 PV.price
from @port_values PV
where PV.pv_id < P.pv_id
and PV.price is not NULL
and PV.id = P.id
and P.price is null
order by PV.pv_id desc ) s
WHERE P.price is NULL
答案 2 :(得分:0)
使用可更新的CTE:
with toupdate as (
select p.*,
lag(p.price) over (partition by p.pv_id order by p.id) as prev_price
from @port_values p
where p.price is not null
)
update toupdate
set price = prev_price;
为了提高性能,您希望在(pv_id, id, price)
上建立索引。在SQL Server的最新版本中,表变量允许使用这些变量。在旧版本中,请使用临时表,以便您可以添加索引。