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 / 问题 / 30325
Accepted
Stuart Blackler
Stuart Blackler
Asked: 2012-12-13 19:05:36 +0800 CST2012-12-13 19:05:36 +0800 CST 2012-12-13 19:05:36 +0800 CST

删除与截断

  • 772

我试图更好地理解DELETEandTRUNCATE命令之间的区别。我对内部结构的理解大致如下:

DELETE-> 数据库引擎从相关数据页和输入该行的所有索引页中查找并删除该行。因此,索引越多,删除所需的时间就越长。

TRUNCATE-> 简单地删除所有表的数据页,使其成为删除表内容的更有效选项。

假设以上是正确的(如果不是,请纠正我):

  1. 不同的恢复模式如何影响每个语句?如果有任何影响
  2. 删除时,是扫描所有索引还是只扫描该行所在的索引?我会假设所有索引都被扫描(而不是寻找?)
  3. 命令是如何复制的?是否在每个订阅者上发送和处理 SQL 命令?还是 MSSQL 比这更智能一些?
sql-server database-internals
  • 2 2 个回答
  • 22366 Views

2 个回答

  • Voted
  1. Best Answer
    Paul White
    2012-12-14T03:02:28+08:002012-12-14T03:02:28+08:00

    DELETE -> 数据库引擎从相关数据页和输入该行的所有索引页中查找并删除该行。因此,索引越多,删除所需的时间就越长。

    是的,尽管这里有两种选择。执行基表删除的同一操作员可以逐行从非聚集索引中删除行。这称为窄(或每行)更新计划:

    每行删除

    或者,非聚集索引删除可以由单独的运算符执行,每个非聚集索引一个。在这种情况下(称为宽或每个索引更新计划),完整的操作集存储在工作表(急切假脱机)中,然后每个索引重播一次,通常按特定非聚集索引的键显式排序以鼓励顺序访问模式。

    每个索引删除

    TRUNCATE -> 简单地删除所有表的数据页,使其成为删除表内容的更有效选项。

    是的。 TRUNCATE TABLE效率更高的原因有很多:

    1. 可能需要更少的锁。截断通常只需要一个表级别的模式修改锁(以及每个解除分配的范围上的排他锁)。删除可能会获得较低(行或页)粒度的锁,以及任何已释放页上的排他锁。
    2. 只有截断才能保证从堆表中释放所有页。即使指定了独占表锁定提示(例如,如果为数据库启用了行版本控制隔离级别),删除也可能会在堆中留下空页。
    3. 截断总是最低限度地记录(不管正在使用的恢复模型)。事务日志中只记录页面释放操作。
    4. 如果对象的大小为 128 或更大,截断可以使用延迟删除。延迟删除意味着实际的释放工作由后台服务器线程异步执行。

    不同的恢复模式如何影响每个语句?有什么影响吗?

    删除总是完全记录(删除的每一行都记录在事务日志中)。如果恢复模式不是 ,则日志记录的内容会有一些小的差异FULL,但这在技术上仍然是完整的日志记录。

    删除时,是扫描所有索引还是只扫描该行所在的索引?我会假设所有索引都被扫描(而不是寻找?)

    删除索引中的一行(使用前面显示的窄更新计划或宽更新计划)始终是按键访问(查找)。扫描删除的每一行的整个索引将是非常低效的。让我们再看一下前面显示的 per-index 更新计划:

    宽计划 2

    执行计划是需求驱动的管道:父操作员(左侧)通过一次向子操作员请求一行来驱动子操作员完成工作。排序运算符是阻塞的(它们必须在生成第一个排序行之前消耗整个输入),但它们仍然由请求第一行的父级(索引删除)驱动。索引删除从完成的排序中一次拉出一行,更新每一行的目标非聚集索引。

    在广泛的更新计划中,您经常会看到基表更新运算符将列添加到行流中。在这种情况下,聚集索引删除将非聚集索引键列添加到流中。存储引擎需要这些数据来定位要从非聚集索引中删除的行:

    输出列表详细信息

    命令是如何复制的?是否在每个订阅者上发送和处理 SQL 命令?还是 SQL Server 比这更智能一些?

    使用事务复制或合并复制发布的表不允许截断。如何复制删除取决于复制的类型及其配置方式。例如,快照复制只是使用批量方法复制表的时间点视图 - 不会跟踪或应用增量更改。事务复制通过读取日志记录并生成适当的事务以将更改应用到订阅者来工作。合并复制使用触发器和元数据表跟踪更改。

    相关阅读:优化更改数据的 T-SQL 查询

    • 61
  2. Pawel W
    2022-08-10T12:25:25+08:002022-08-10T12:25:25+08:00

    sql截断命令

    1. 它是一个 DDL(数据定义语言)命令,因此 COMMIT 和 ROLLBACK 等命令不适用于该命令(这里的例外是 PostgreSQL 和 MSSQL,它们的 TRUNCATE 命令实现允许在事务中使用该命令)

    2. 您无法撤消删除记录的操作,它会自动发生且不可逆(上述例外情况除外 - 但前提是该操作包含在 TRANSACTION 块中且会话未关闭)。在 Oracle 的情况下 - 包括两个隐式提交,一个在执行语句之前,一个在执行语句之后。因此,该命令无法撤回,而运行时错误将导致无论如何提交

    3. 从表中删除所有记录,记录不能被限制删除。对于 Oracle,当按分区拆分表时,可以单独截断(TRUNCATE)各个分区,从而可以从表中部分删除所有数据

    4. 释放表中数据占用的空间(在 TABLESPACE - 磁盘上)。对于 Oracle - 如果您使用 REUSE STORAGE 子句,则不会回滚数据段,即您将保留分配给表的已删除行的空间,如果要重新加载表中的数据,这可能会更有效. 高分将被重置

    5. 将分配给表的 SEQUENCE 值重置为零。但是,可以使用以下选项:RESTART IDENTITY 或 CONTINUE IDENTITY

    6. TRUNCATE 比 DELETE 快得多

    7. TRUNCATE 生成的重做和撤消的数量可以忽略不计

    8. TRUNCATE 操作使不可用的索引再次可用

    9. 当启用的外键引用另一个表时,不能使用 TRUNCATE,那么您可以:

    • 执行命令:DROP CONSTRAINT,然后TRUNCATE,然后通过CREATE CONSTRAINT或者
    • 执行命令:SET FOREIGN_KEY_CHECKS = 0; 然后 TRUNCATE,然后: SET_FOREIGN_KEY_CHECKS = 1;
    1. TRUNCATE 需要独占表锁,因此关闭独占表锁是一种防止对表进行 TRUNCATE 操作的方法

    2. DML 触发器在执行 TRUNCATE 后不会触发(因此在这种情况下要非常小心,如果在表中定义了删除触发器来执行自动表清理或行删除后的登录操作,则不应使用 TRUNCATE)。在 Oracle 上,触发 DDL 触发器

    sql删除命令

    1. 它是一个 DML(数据操作语言)命令,因此以下命令用于该命令:COMMIT 和 ROLLBACK

    2. 可以使用 ROLLBACK 命令撤消删除记录的操作

    3. 从表中删除全部或部分记录,可以使用 WHERE 子句限制要删除的记录

    4. 不释放表中数据占用的空间(在 TABLESPACE - 磁盘上)

    5. 不重置分配给表的 SEQUENCE 值

    6. DELETE 比 TRUNCATE 慢得多

    7. DELETE 生成少量重做和大量撤消

    8. DELETE 操作不会使不可用的索引再次可用

    9. DELETE 如果启用的外键引用另一个表,可以(或不)应用取决于外键配置(如果没有),请:

    • 执行命令:DROP CONSTRAINT,然后TRUNCATE,然后通过CREATE CONSTRAINT或者
    • 执行命令:SET FOREIGN_KEY_CHECKS = 0; 然后 TRUNCATE,然后: SET_FOREIGN_KEY_CHECKS = 1;
    1. DELETE 需要共享表锁

    2. 触发器触发

    更多细节: https ://rozwoj-oprogramowania.pl/en/blog/databases/truncate-vs-delete.html

    问候

    • 0

相关问题

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

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

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

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

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

Sidebar

Stats

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

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • 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
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +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