【问题标题】:SQL Query Performance TuningSQL 查询性能调优
【发布时间】:2014-06-12 10:07:59
【问题描述】:
UPDATE nas_backup
SET fiber_serviceability_class = '0', 
last_updated_ts = CURRENT_TIMESTAMP 
WHERE location_id IN ( 
SELECT location_id 
FROM ( 
WITH distinct_locs AS ( 
    SELECT location_id, boundary_type 
    FROM ( 
        SELECT location_id, boundary_type 
        FROM nc
        WHERE technology_type = 'Fibre' 
    ) 
    GROUP BY location_id, boundary_type 
    HAVING COUNT( * ) = 1
)
SELECT nas.location_id
FROM distinct_locs, nas_backup nas
WHERE distinct_locs.location_id = nas.location_id
AND distinct_locs.boundary_type = 'FSA'
GROUP BY nas.location_id
)
);

谁能建议一种优化查询的方法。现在需要超过 5 分钟。

表 nc 有 1600 万条记录,表 nas_backup 有 200 万条记录。

【问题讨论】:

  • 您没有提到任何索引,因此添加这些将是一个不错的起点。
  • 相关列的索引已经到位。我只想要一个更优化的查询版本。
  • 如果您能提供实际的执行计划,我们或许能够确定瓶颈在哪里?
  • 只是为了确保我理解您的目标:您希望更新nas_backup 中的所有记录,其中位置的技术类型为“光纤”,边界类型为“FSA”。还有什么要检查的吗?

标签: sql sql-tuning


【解决方案1】:

EXISTS 可以帮助您一点。试试看:

UPDATE nas_backup
SET fiber_serviceability_class = '0', 
last_updated_ts = CURRENT_TIMESTAMP 
-- Remove the IN condition and check only that at least one row exists
WHERE EXISTS ( 
SELECT location_id 
FROM ( 
    WITH distinct_locs AS ( 
        SELECT location_id, boundary_type 
        FROM ( 
            SELECT location_id, boundary_type 
            FROM nc
            WHERE technology_type = 'Fibre'
        ) 
        GROUP BY location_id, boundary_type 
        HAVING COUNT( * ) = 1
    )
    SELECT
        nas.location_id
    FROM
        distinct_locs
    WHERE
        distinct_locs.boundary_type = 'FSA'
        -- This is the new line
        AND distinct_locs.location_id = nas_backup.location_id
    GROUP BY
        nas.location_id
    )
);

但是,如果您将您的数据库结构和目标分享给我们,会更容易提供帮助。

下次请与我们分享您使用的 DBMS 的供应商和版本。

【讨论】:

  • 谢谢 Pred。但我想知道你为什么在最后包含新行。该条件已包含在原始查询中。
  • 该行应该引用您正在更新的表。这就是我包含的原因(这就是为什么我没有使用 nas 别名,而是使用表名。该条件将子查询链接到原始表。
  • 我刚刚编辑了答案。我从上次选择中删除了“加入”。
【解决方案2】:

我在这里说的大部分事情无论如何都应该由一个好的优化器完成,所以这主要是为了更好的可读性。

您已应用于位置部分的所有过滤器,因此将其带到子查询以减少结果集:

SELECT location_id, boundary_type 
FROM nc 
WHERE technology_type = 'Fibre' AND nc.boundary_type='FSA'
GROUP BY location_id, boundary_type 
HAVING COUNT(*) = 1

接下来,使用 JOIN 语法而不是隐式 Join:

UPDATE nas fiber_serviceability_class = '0', last_updated_ts = CURRENT_TIMESTAMP 
FROM nas_backup nas
    JOIN (SELECT location_id, boundary_type 
            FROM nc 
            WHERE technology_type = 'Fibre' AND nc.boundary_type='FSA'
            GROUP BY location_id, boundary_type 
            HAVING COUNT(*) = 1) loc ON loc.location_id=nas.location_id

不知道带有HAVING子句的子查询是否有特殊原因。在不知道您的结构和数据的情况下,这只是一个猜测,但也许您不需要。这是一个非常简单的查询,转换为“同时更新技术类型为 Fiber 且边界类型为 FSA 的每个 nas_backup”。

UPDATE nas fiber_serviceability_class = '0', last_updated_ts = CURRENT_TIMESTAMP 
FROM nas_backup nas
    JOIN nc ON nas.location_id=nc.location_id
WHERE nc.technology_type='Fibre'
    AND nc.boundary_type='FSA'

【讨论】:

    猜你喜欢
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多