避免全表扫描

问题描述 投票:2回答:3

我有以下查询的问题

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有大约400k行的情况下。它显然是在进行迭代表扫描而根本没有效率。我已经尝试将索引放在具有任何性能的列上。

构建像这样的查询最有效的方法是什么?

sql sql-server tsql sql-server-2017
3个回答
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

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

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中,这些表变量是允许的。在旧版本中,使用临时表以便添加索引。

© www.soinside.com 2019 - 2024. All rights reserved.