有没有办法加快对 t1 和 t1 中百万行的查询?

Posted

技术标签:

【中文标题】有没有办法加快对 t1 和 t1 中百万行的查询?【英文标题】:Is there a way to speed up this query for million rows in both t1 and t1? 【发布时间】:2022-01-12 12:02:34 【问题描述】:

表 t1 的主键为 NUMBER,我们必须使用表 t2 的行设置属性 A、B、C、...,因此使用 PIVOT。

此查询的执行时间超过 4 小时。

有什么办法可以改善吗?

DECLARE @number [varchar](40)

    DECLARE cursor CURSOR FOR 
    SELECT DISTINCT(t1.NUMBER) 
    FROM [TABLE1] t1
    INNER JOIN [TABLE2] t2
    ON t1.NUMBER = t2.NUMBER

    OPEN cursor

    BEGIN TRANSACTION
    FETCH NEXT FROM cursor INTO @number

    WHILE(@@FETCH_STATUS = 0)
        BEGIN
        UPDATE t1
        SET A = piv.A,
            B= piv.B,
            C= piv.C, ...
        FROM
            (SELECT A, B, C, ... 
            FROM
                (SELECT VALUE, NAME
                FROM t2
                WHERE NUMBER = @number
                ) d
                PIVOT
                (MAX(VALUE)
                FOR NAME IN (A, B, C, ...
                ) p
            ) AS piv
        WHERE t1.NUMBER = @number

    FETCH NEXT FROM cursor INTO @number
    END
    COMMIT TRANSACTION

【问题讨论】:

摆脱WHILE 将是一个重要的开始。你为什么用一个? SQL 是一种基于集合的语言,它可以轻松处理在单个语句中插入超过 100 万行。 为什么这需要一个游标,没有什么不能作为一个单一的基于集合的更新来完成,这可能会快一个数量级。 【参考方案1】:

以 SQL 方式执行。

从 Pivot 更新。

UPDATE t1
SET A = t2.A
  , B = t2.B
  , C = t2.C
FROM TABLE1 t1
JOIN (
    SELECT *
    FROM (
      SELECT [NUMBER], NAME, [VALUE]
      FROM TABLE2
      WHERE NAME IN ('A','B','C')
    ) Src
    PIVOT (
      MAX([VALUE])
      FOR NAME IN ([A],[B],[C]) 
    ) Pvt
) t2 ON t2.[NUMBER] = t1.[NUMBER]

更新前

select * from TABLE1
NUMBER A B C
1 null null null
2 null null null

更新后

select * from TABLE1
NUMBER A B C
1 a one be one you see
2 a two is too too be or not to see

dbfiddle here

上的演示

【讨论】:

以上是关于有没有办法加快对 t1 和 t1 中百万行的查询?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法删除这种类型的 SQL SELECT 中的嵌套查询?

使用触发器中断 Oracle 数据库删除和更新行

对超过百万行进行排序的分组

用其他行的 SUM() 和 COUNT() 更新一行

具有 10+ 百万行的 MySQL 表 - 如何使用索引加快搜索速度?

优化 100 万行的查询