AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 320399
Accepted
DBA Greg14
DBA Greg14
Asked: 2022-12-01 06:42:55 +0800 CST2022-12-01 06:42:55 +0800 CST 2022-12-01 06:42:55 +0800 CST

用于批量删除的 CTE 与临时表

  • 772

这里有两部分问题。

我们有一个大表(在 1-2 百万行之间),上面有非常频繁的 DML 操作。在低流量期间,我们有一个代理作业来删除旧行以控制表的大小。它使用下面的 CTE,它在运行时会导致大量阻塞:

;with agent_cte (queue_id) as 
(
   select top (3000) queue_id
   from Table_A with (updlock, readpast)
   where state in ('success','error','reject','failed','deleted')
   and modify_timestamp <= DATEADD(dd,- 5,getdate())
   order by modify_timestamp asc
)
   delete from agent_cte 
;

CTE 查询计划

我重新编写了它以使用临时表来加速查询并减少阻塞,但我发现使用IN与EXISTS确定要删除的行之间存在很大的性能差异。

IN版本:

-- Create temp Table
create table #Table_AToDelete
    (Queue_id uniqueidentifier,
    PRIMARY KEY(Queue_id)
    );

-- grab top 3k queue_id's older than 5 days, insert into temp table
    Insert into #Table_AToDelete
        select top (3000) queue_id
        from Table_A with (nolock)
        where state in ('success','error','reject','failed','deleted')
        and modify_timestamp <= DATEADD(dd,- 5,getdate())

-- delete the rows from table_A based on rows in temp table
    delete 
        from Table_A
        where queue_id in (select queue_id from #Table_AToDelete)

临时表计划

这个版本在 40-50 秒内运行,但是当我用下面的 delete 语句替换最后一行时:

where exists(select queue_id from #Table_AToDelete)

2分钟后它还在运行,所以我取消了它。

所以,问题:

  1. 我以前见过用于帮助阻塞和性能的临时表,但不完全理解为什么它会比使用 CTE 执行得更好?我们确实有一个索引Queue_id。
  2. IN为什么delete和delete 中的性能差异很大EXISTS?

关于如何调整它以更好地执行或进一步减少阻塞的任何反馈?

更多注意事项:

  • 使用粘贴计划(上面的链接)可以使用 CTE 和临时表。
  • 其他两个具有级联更新和删除的表有 FK,CTE 计划将更多时间花在删除那里,而临时表版本将更多时间花在主表上。
  • 一般来说,与 CTE 相比,使用这样的临时表是否有性能优势?
  • 我不允许发布表模式,所以如果计划没有足够的信息,我深表歉意。

我还将使用本文中的视图进行测试。

sql-server
  • 2 2 个回答
  • 149 Views

2 个回答

  • Voted
  1. Best Answer
    Erik Darling
    2022-12-02T04:40:17+08:002022-12-02T04:40:17+08:00

    诡异的

    两个查询中的性能问题与 CTE 与临时表无关。我看到时间上有差异,但请听我说完。

    只是删除

    在直接删除中,您花费最多时间从表中删除,而不是从中进行选择。

    坚果

    此查询中的等待都与读取和写入磁盘有关:

    坚果

    #临时表

    从 #temp 表中删除的查询计划显示在相同的两个地方花费的时间最多(只是更多时间):

    坚果

    等待此查询的瓶颈与以前相同,只是更多:

    坚果

    差异

    考虑到这两个查询都面临硬件困难,我有一半希望时间差异不可重复或不可靠,而更多是偶然事件。

    由于它们是可重复的,因此您应该注意对两个查询应用相同的提示。您的第一个查询已(updlock, readpast)指定。通过提示跳过行锁readpast可能是这里出现明显差异的原因。

    从文档:

    指定 READPAST 时,将跳过行级锁但不会跳过页级锁。

    由于该锁定提示在这里没有多大意义,请尝试在您的查询中使用paglock或tablock提示以跳过行级锁定。

    再次注意等待统计信息:

    坚果

    在较慢的查询中,等待计数是较快查询的约 2 倍。

    无论如何,您使用的硬件与生产数据库工作负载不兼容。

    • 4
  2. Peter
    2022-12-01T09:57:41+08:002022-12-01T09:57:41+08:00
    1. 哪个更好取决于用途。您可以查看这篇文章了解更多信息。https://www.brentozar.com/archive/2019/06/whats-better-ctes-or-temp-tables/
    2. 这是因为您的 EXISTS 查询有误,现在只要临时表中有数据,它就会从该表中删除所有内容。您应该将该行替换为:

    哪里存在(从#Table_AToDelete 中选择 1 作为 WHERE a.queue_id = A.queue_id)

    假设在真实表中还有一个名为queue_id 的列。

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve