PostgreSQL 表膨胀的终极指南:诊断、优化与实战演练
PostgreSQL 表膨胀的终极指南:诊断、优化与实战演练
一、什么是表膨胀?
1.1 表膨胀的成因
1.2 表膨胀的影响
二、诊断表膨胀
2.1 查看表的大小和膨胀情况
2.2 监控 VACUUM 和 ANALYZE 操作
2.3 检查索引的健康状况
2.4 分析慢查询日志
三、解决表膨胀问题
3.1 调整 autovacuum 配置
3.2 手动执行 VACUUM 和 ANALYZE 操作
3.3 优化索引
3.4 优化数据类型选择
3.5 优化查询语句
3.6 使用分区表
3.7 其他优化技巧
四、大批量数据导入时的注意事项
4.1 关闭 autovacuum
4.2 禁用触发器和外键约束
4.3 增加 WAL 缓冲区大小
4.4 批量提交事务
4.5 手动执行 ANALYZE 操作
五、高并发环境下的表膨胀问题
5.1 优化 autovacuum 配置
5.2 优化查询语句和索引
5.3 减少长时间运行的事务
5.4 监控数据库性能
六、总结
七、附录:常用命令和 SQL 语句
PostgreSQL 表膨胀的终极指南:诊断、优化与实战演练
大家好,我是老码农。今天我们来聊聊 PostgreSQL 数据库中一个让人头疼的问题——表膨胀。表膨胀不仅会影响数据库的性能,还会导致存储空间浪费,甚至可能引发系统崩溃。所以,了解表膨胀的成因、诊断方法和优化策略,对于 PostgreSQL 开发者和运维人员来说至关重要。
一、什么是表膨胀?
简单来说,表膨胀是指数据库表中的数据量虽然没有显著增加,但表文件的大小却不断增长的现象。这就像你的衣柜,虽然衣服没怎么变多,但由于整理不当,导致空间被浪费,衣柜看起来越来越拥挤。
1.1 表膨胀的成因
PostgreSQL 的 MVCC(Multi-Version Concurrency Control,多版本并发控制)机制是导致表膨胀的主要原因。当我们对表中的数据进行更新或删除操作时,PostgreSQL 并不会立即覆盖旧的数据,而是创建一个新的版本。旧版本的数据会保留一段时间,以便支持并发的事务。当旧版本的数据不再被任何事务需要时,PostgreSQL 会通过 VACUUM 操作来清理这些“死数据”,从而回收存储空间。但是,如果 VACUUM 操作不及时或不充分,就会导致表膨胀。
除了 MVCC 机制,以下因素也会加剧表膨胀:
- 频繁的更新和删除操作: 每次更新或删除都会产生新的版本,如果没有及时清理,就会导致表膨胀。
- 长时间运行的事务: 长时间运行的事务会阻止 VACUUM 清理旧数据,从而导致表膨胀。
- 未优化的索引: 索引的更新也会产生旧版本,如果没有及时清理,也会导致表膨胀。此外,不合理的索引设计也会导致表膨胀。
- 数据类型选择不当: 例如,使用了过长的文本类型,即使存储的数据量不大,也会导致表膨胀。
- autovacuum 配置不当: autovacuum 负责自动执行 VACUUM 操作。如果 autovacuum 配置不当,例如,触发条件设置过于保守或资源限制过于严格,会导致 VACUUM 操作不及时或不充分。
1.2 表膨胀的影响
表膨胀会带来一系列负面影响:
- 性能下降: 数据库需要扫描更多的页面来查找数据,导致查询速度变慢。
- 存储空间浪费: 存储空间被无用的旧数据占用,导致存储成本增加。
- I/O 负载增加: 读取和写入数据的 I/O 操作增加,导致服务器负载增加。
- 索引性能下降: 索引文件也会膨胀,导致索引查询效率下降。
- 数据库备份和恢复时间延长: 数据库备份和恢复的时间会随着表的大小增加而延长。
- 潜在的系统崩溃风险: 当磁盘空间耗尽时,数据库可能会无法正常工作,甚至崩溃。
二、诊断表膨胀
在解决表膨胀问题之前,我们需要先诊断问题。以下是一些常用的诊断方法:
2.1 查看表的大小和膨胀情况
我们可以使用以下 SQL 语句来查看表的大小和膨胀情况:
-- 查看表的大小和膨胀情况 SELECT schemaname, tablename, pg_size_pretty(pg_table_size(schemaname || '.' || tablename)) AS table_size, pg_size_pretty(pg_indexes_size(schemaname || '.' || tablename)) AS index_size, pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size, n_dead_tup AS dead_tuples, last_autovacuum, last_vacuum, last_autoanalyze, last_analyze FROM pg_stat_all_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY pg_table_size(schemaname || '.' || tablename) DESC;
这个 SQL 语句会返回以下信息:
schemaname
:表所在的模式名。tablename
:表名。table_size
:表的数据文件大小。index_size
:表的索引文件大小。total_size
:表的总大小(数据文件 + 索引文件)。dead_tuples
:表中未被清理的“死元组”数量,可以间接反映表膨胀的程度。 dead_tuples 越多,表明表膨胀越严重。last_autovacuum
:上次 autovacuum 操作的时间。last_vacuum
:上次手动 vacuum 操作的时间。last_autoanalyze
:上次 autovacuum analyze 操作的时间。last_analyze
:上次手动 analyze 操作的时间。
通过查看 table_size
、index_size
和 dead_tuples
,我们可以初步判断表是否膨胀。
2.2 监控 VACUUM 和 ANALYZE 操作
VACUUM 和 ANALYZE 是解决表膨胀问题的关键。我们需要监控这两个操作的执行情况。
- 监控 autovacuum: autovacuum 是 PostgreSQL 的一个后台进程,负责自动执行 VACUUM 和 ANALYZE 操作。我们可以通过查看 PostgreSQL 的日志来监控 autovacuum 的执行情况。如果 autovacuum 执行频率不够或者执行时间过长,可能需要调整 autovacuum 的配置。
- 监控手动 VACUUM 和 ANALYZE: 在某些情况下,我们需要手动执行 VACUUM 和 ANALYZE 操作。我们可以使用
pg_stat_activity
视图来监控手动 VACUUM 和 ANALYZE 操作的执行情况。
-- 查看当前正在执行的 VACUUM 和 ANALYZE 操作 SELECT pid, usename, datname, application_name, query, backend_start, state, wait_event_type, wait_event FROM pg_stat_activity WHERE query ILIKE '%vacuum%' OR query ILIKE '%analyze%';
2.3 检查索引的健康状况
索引也会受到表膨胀的影响。我们可以使用以下 SQL 语句来检查索引的健康状况:
-- 检查索引的健康状况 SELECT schemaname, tablename, indexname, indexdef, pg_size_pretty(pg_relation_size(indexrelid)) AS index_size, idx_scan, -- 索引扫描次数 idx_tup_read, -- 从索引中读取的元组数 idx_tup_fetch -- 从索引中获取的元组数 FROM pg_stat_all_indexes WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY pg_relation_size(indexrelid) DESC;
这个 SQL 语句会返回以下信息:
schemaname
:索引所在的模式名。tablename
:表名。indexname
:索引名。indexdef
:索引定义。index_size
:索引文件大小。idx_scan
:索引扫描次数。如果扫描次数很低,可能表明索引没有被充分利用,需要检查查询语句是否使用了该索引,或者考虑删除该索引。idx_tup_read
:从索引中读取的元组数。idx_tup_fetch
:从索引中获取的元组数。如果idx_tup_read
远大于idx_tup_fetch
,可能表明索引效率较低,需要优化索引或者查询语句。
2.4 分析慢查询日志
慢查询日志可以帮助我们找到导致表膨胀的原因。通过分析慢查询日志,我们可以发现哪些查询语句频繁地更新或删除数据,从而产生大量的“死元组”。
三、解决表膨胀问题
诊断出表膨胀问题后,我们需要采取相应的措施来解决。以下是一些常用的优化策略:
3.1 调整 autovacuum 配置
autovacuum 是解决表膨胀问题的核心。我们需要根据实际情况调整 autovacuum 的配置。以下是一些常用的 autovacuum 配置参数:
autovacuum
:是否启用 autovacuum。默认为on
。autovacuum_max_workers
:autovacuum 并行工作进程的最大数量。默认为 3。autovacuum_naptime
:autovacuum 进程休眠的时间(秒)。默认为 1 分钟。autovacuum_vacuum_threshold
:触发 VACUUM 的最小元组数。默认为 50。autovacuum_analyze_threshold
:触发 ANALYZE 的最小元组数。默认为 50。autovacuum_vacuum_scale_factor
:触发 VACUUM 的比例(表行数的百分比)。默认为 0.2(20%)。autovacuum_analyze_scale_factor
:触发 ANALYZE 的比例(表行数的百分比)。默认为 0.1(10%)。autovacuum_vacuum_cost_delay
:VACUUM 操作的开销延迟(毫秒)。默认为 2 毫秒。autovacuum_vacuum_cost_limit
:VACUUM 操作的开销限制。默认为 200。autovacuum_freeze_min_age
:在进行 VACUUM FREEZE 之前,元组需要存在的最短时间(事务数)。默认为 500000000。autovacuum_freeze_max_age
:在进行 VACUUM FREEZE 之前,元组可以存在的最长时间(事务数)。默认为 200000000。
我们可以通过修改 postgresql.conf
文件或者使用 ALTER TABLE
命令来修改这些参数。例如:
-- 修改 autovacuum 配置(全局) ALTER SYSTEM SET autovacuum_max_workers = 5; -- 修改 autovacuum 配置(针对特定表) ALTER TABLE mytable SET (autovacuum_vacuum_scale_factor = 0.1);
注意: 修改 postgresql.conf
文件后,需要重启 PostgreSQL 服务才能使配置生效。使用 ALTER TABLE
命令修改参数,则立即生效。
调整建议:
- 提高 autovacuum_max_workers: 在高并发环境下,可以适当提高
autovacuum_max_workers
的值,以提高 VACUUM 的并行处理能力。 - 减小 autovacuum_vacuum_scale_factor 和 autovacuum_analyze_scale_factor: 对于更新和删除操作频繁的表,可以适当减小
autovacuum_vacuum_scale_factor
和autovacuum_analyze_scale_factor
的值,以便更频繁地触发 VACUUM 和 ANALYZE 操作。 - 调整 autovacuum_vacuum_cost_delay 和 autovacuum_vacuum_cost_limit: 如果服务器的 I/O 负载较高,可以适当增加
autovacuum_vacuum_cost_delay
的值,以限制 VACUUM 操作的 I/O 消耗。同时,也可以适当减小autovacuum_vacuum_cost_limit
的值。 - 根据表的更新频率和数据量,动态调整 autovacuum 的配置: 对于更新频率高、数据量大的表,可以设置更积极的 VACUUM 和 ANALYZE 策略;对于更新频率低、数据量小的表,可以设置更保守的策略。
3.2 手动执行 VACUUM 和 ANALYZE 操作
在某些情况下,我们需要手动执行 VACUUM 和 ANALYZE 操作。例如:
- 在导入大量数据后: 导入大量数据后,需要手动执行 ANALYZE 操作,以便更新统计信息,提高查询性能。
- 在进行大量更新或删除操作后: 在进行大量更新或删除操作后,需要手动执行 VACUUM 操作,以便清理“死元组”,回收存储空间。
- 在 autovacuum 配置不当或无法满足需求时: 如果 autovacuum 配置不当或无法满足需求,可以手动执行 VACUUM 和 ANALYZE 操作。
以下是手动执行 VACUUM 和 ANALYZE 操作的 SQL 语句:
-- 执行 VACUUM 操作 VACUUM mytable; -- 执行 VACUUM FULL 操作(会锁定表,谨慎使用) VACUUM FULL mytable; -- 执行 ANALYZE 操作 ANALYZE mytable;
注意:
VACUUM FULL
操作会锁定表,在生产环境中应谨慎使用。因为它会导致表在 vacuum 期间无法被读写。 可以考虑在系统低峰期执行。VACUUM
操作不会锁定表,可以在线执行。ANALYZE
操作不会锁定表,可以在线执行。- 手动执行 VACUUM 和 ANALYZE 操作时,可以根据需要添加
VERBOSE
选项,以便查看详细的执行信息。
3.3 优化索引
不合理的索引设计也会导致表膨胀。我们需要优化索引,以提高查询性能和减少表膨胀。
- 删除不必要的索引: 删除不被查询使用的索引,可以减少索引的维护成本,从而减少表膨胀。
- 优化索引的列顺序: 根据查询的 WHERE 子句,优化索引的列顺序。将经常被用作查询条件的列放在索引的前面。
- 使用合适的索引类型: 根据查询的类型,选择合适的索引类型。例如,对于范围查询,可以使用 B-tree 索引;对于全文搜索,可以使用 GIN 或 GIST 索引。
- 重建索引: 当索引出现碎片化时,需要重建索引。重建索引可以优化索引的性能,从而减少表膨胀。
-- 重建索引 REINDEX INDEX myindex; -- 重建表的所有索引 REINDEX TABLE mytable;
注意: 重建索引会锁定表,在生产环境中应谨慎使用。 可以考虑在系统低峰期执行。
3.4 优化数据类型选择
选择合适的数据类型可以减少存储空间,从而减少表膨胀。
- 使用更小的数据类型: 例如,如果一个列只需要存储整数,可以使用
SMALLINT
或INTEGER
,而不是BIGINT
。 - 使用变长数据类型: 对于文本类型,可以使用
VARCHAR
或TEXT
,而不是CHAR
,避免浪费存储空间。 - 避免使用过长的文本类型: 如果一个列只需要存储较短的文本,可以使用
VARCHAR
,并设置合适的长度限制。 - 使用压缩: 对于存储大量文本数据的表,可以使用数据压缩功能。例如,可以使用
CREATE TABLE
语句的WITH (toast_compression = 'pglz')
子句来启用数据压缩。
3.5 优化查询语句
低效的查询语句会导致大量的更新和删除操作,从而加剧表膨胀。我们需要优化查询语句,以减少更新和删除操作。
- 使用
WHERE
子句过滤数据: 在查询时,尽量使用WHERE
子句过滤数据,避免全表扫描。 - 避免使用
SELECT *
: 只选择需要的列,避免选择不必要的列。 - 优化
JOIN
操作: 优化JOIN
操作,使用索引,避免全表扫描。 - 避免使用子查询: 尽量使用
JOIN
或 CTE(Common Table Expression,公共表表达式)替代子查询。 - 避免使用
LIKE '%...'
: 避免使用以通配符开头的LIKE
语句,因为这会导致全表扫描。 - 使用
EXPLAIN
分析查询计划: 使用EXPLAIN
分析查询计划,找出低效的查询语句,并进行优化。
3.6 使用分区表
对于数据量非常大的表,可以考虑使用分区表。分区表将数据分割成多个子表,可以提高查询性能,减少表膨胀。
- 按时间分区: 例如,可以按月或按年分区,方便进行数据归档和删除。
- 按范围分区: 例如,可以按 ID 范围分区,方便进行数据查询。
- 按列表分区: 例如,可以按国家或地区分区,方便进行数据查询。
3.7 其他优化技巧
- 定期备份和恢复: 定期备份和恢复数据库,可以清除旧的事务日志,减少表膨胀。
- 监控磁盘空间: 监控磁盘空间,及时清理磁盘空间,避免磁盘空间耗尽。
- 升级 PostgreSQL 版本: 新版本的 PostgreSQL 通常会修复一些表膨胀相关的 bug,并提供更好的性能优化。
- 考虑使用外部表: 对于不需要经常访问的数据,可以考虑使用外部表,将数据存储在其他地方,例如,文件或云存储。
四、大批量数据导入时的注意事项
在大批量数据导入时,表膨胀问题更容易发生。我们需要特别注意以下几点:
4.1 关闭 autovacuum
在大批量数据导入期间,关闭 autovacuum 可以避免 VACUUM 和 ANALYZE 操作干扰数据导入,从而提高导入速度。导入完成后,再开启 autovacuum。
-- 关闭 autovacuum ALTER TABLE mytable SET (autovacuum_enabled = false); -- 导入数据... -- 开启 autovacuum ALTER TABLE mytable SET (autovacuum_enabled = true);
4.2 禁用触发器和外键约束
触发器和外键约束会增加数据导入的开销。在大批量数据导入期间,可以禁用触发器和外键约束,以提高导入速度。导入完成后,再启用触发器和外键约束。
-- 禁用触发器 ALTER TABLE mytable DISABLE TRIGGER ALL; -- 禁用外键约束 ALTER TABLE mytable DISABLE TRIGGER ALL; -- 禁用所有触发器 ALTER TABLE mytable NOCHECK CONSTRAINT ALL; -- 禁用所有外键约束 -- 导入数据... -- 启用触发器 ALTER TABLE mytable ENABLE TRIGGER ALL; -- 启用外键约束 ALTER TABLE mytable ENABLE TRIGGER ALL; -- 启用所有触发器 ALTER TABLE mytable CHECK CONSTRAINT ALL; -- 启用所有外键约束
注意: 在禁用触发器和外键约束时,需要确保导入的数据符合数据的完整性约束。否则,会导致数据错误。
4.3 增加 WAL 缓冲区大小
WAL(Write-Ahead Logging,预写日志)用于保证数据的持久性。在大批量数据导入时,可以增加 WAL 缓冲区的大小,以提高写入性能。
-- 修改 WAL 缓冲区大小(全局) ALTER SYSTEM SET wal_buffers = '64MB'; -- 示例,可以根据实际情况调整
注意: 修改 wal_buffers
的值需要重启 PostgreSQL 服务才能生效。
4.4 批量提交事务
将数据分成多个批次提交事务,可以减少事务的开销。在大批量数据导入时,可以使用批量提交事务的方式,提高导入速度。
-- 批量提交事务 BEGIN; -- 导入一批数据 ... COMMIT; BEGIN; -- 导入另一批数据 ... COMMIT;
4.5 手动执行 ANALYZE 操作
在大批量数据导入完成后,需要手动执行 ANALYZE 操作,以便更新统计信息,提高查询性能。
-- 执行 ANALYZE 操作 ANALYZE mytable;
五、高并发环境下的表膨胀问题
在高并发环境下,表膨胀问题会更加严重。我们需要特别注意以下几点:
5.1 优化 autovacuum 配置
在高并发环境下,autovacuum 的配置至关重要。我们需要根据实际情况调整 autovacuum 的配置,以适应高并发的场景。例如:
- 提高 autovacuum_max_workers: 在高并发环境下,可以适当提高
autovacuum_max_workers
的值,以提高 VACUUM 的并行处理能力。 - 减小 autovacuum_vacuum_scale_factor 和 autovacuum_analyze_scale_factor: 在高并发环境下,更新和删除操作更频繁,可以适当减小
autovacuum_vacuum_scale_factor
和autovacuum_analyze_scale_factor
的值,以便更频繁地触发 VACUUM 和 ANALYZE 操作。 - 调整 autovacuum_vacuum_cost_delay 和 autovacuum_vacuum_cost_limit: 在高并发环境下,服务器的 I/O 负载较高,可以适当增加
autovacuum_vacuum_cost_delay
的值,以限制 VACUUM 操作的 I/O 消耗。同时,也可以适当减小autovacuum_vacuum_cost_limit
的值。
5.2 优化查询语句和索引
在高并发环境下,查询语句和索引的性能对整体性能至关重要。我们需要优化查询语句和索引,以减少锁竞争和提高查询效率。
- 使用
WHERE
子句过滤数据: 在查询时,尽量使用WHERE
子句过滤数据,避免全表扫描。 - 避免使用
SELECT *
: 只选择需要的列,避免选择不必要的列。 - 优化
JOIN
操作: 优化JOIN
操作,使用索引,避免全表扫描。 - 避免使用子查询: 尽量使用
JOIN
或 CTE 替代子查询。 - 避免使用
LIKE '%...'
: 避免使用以通配符开头的LIKE
语句,因为这会导致全表扫描。 - 使用
EXPLAIN
分析查询计划: 使用EXPLAIN
分析查询计划,找出低效的查询语句,并进行优化。 - 删除不必要的索引: 删除不被查询使用的索引,可以减少索引的维护成本,从而减少表膨胀。
- 优化索引的列顺序: 根据查询的 WHERE 子句,优化索引的列顺序。将经常被用作查询条件的列放在索引的前面。
- 使用合适的索引类型: 根据查询的类型,选择合适的索引类型。例如,对于范围查询,可以使用 B-tree 索引;对于全文搜索,可以使用 GIN 或 GIST 索引。
- 重建索引: 当索引出现碎片化时,需要重建索引。重建索引可以优化索引的性能,从而减少表膨胀。
5.3 减少长时间运行的事务
长时间运行的事务会阻止 VACUUM 清理旧数据,从而导致表膨胀。在高并发环境下,我们需要尽量减少长时间运行的事务。
- 将大事务拆分成小事务: 将大事务拆分成多个小事务,可以减少事务的锁定时间,提高并发性能。
- 避免在事务中执行耗时的操作: 避免在事务中执行耗时的操作,例如,网络 I/O、文件 I/O 等。
- 使用
autocommit
模式: 如果可以,可以使用autocommit
模式,让每个 SQL 语句都成为一个独立的事务。
5.4 监控数据库性能
在高并发环境下,我们需要实时监控数据库的性能,及时发现和解决问题。
- 监控 CPU 使用率、内存使用率、磁盘 I/O 等指标: 监控 CPU 使用率、内存使用率、磁盘 I/O 等指标,可以及时发现性能瓶颈。
- 监控慢查询日志: 监控慢查询日志,可以找出低效的查询语句,并进行优化。
- 监控锁等待: 监控锁等待,可以找出锁竞争的问题,并进行优化。
- 使用性能监控工具: 可以使用一些性能监控工具,例如,
pg_stat_statements
、pgAdmin
等,来监控数据库的性能。
六、总结
表膨胀是 PostgreSQL 数据库中一个常见的问题,如果不及时解决,会严重影响数据库的性能和稳定性。作为 PostgreSQL 开发者和运维人员,我们需要了解表膨胀的成因、诊断方法和优化策略,并根据实际情况采取相应的措施。希望本指南能帮助大家更好地理解和解决 PostgreSQL 表膨胀问题。记住,持续的监控和优化是保持数据库健康的关键!
祝大家在 PostgreSQL 的世界里玩得开心!
七、附录:常用命令和 SQL 语句
- 查看表大小和膨胀情况:
SELECT schemaname, tablename, pg_size_pretty(pg_table_size(schemaname || '.' || tablename)) AS table_size, pg_size_pretty(pg_indexes_size(schemaname || '.' || tablename)) AS index_size, pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size, n_dead_tup AS dead_tuples, last_autovacuum, last_vacuum, last_autoanalyze, last_analyze FROM pg_stat_all_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY pg_table_size(schemaname || '.' || tablename) DESC;
- 查看当前正在执行的 VACUUM 和 ANALYZE 操作:
SELECT pid, usename, datname, application_name, query, backend_start, state, wait_event_type, wait_event FROM pg_stat_activity WHERE query ILIKE '%vacuum%' OR query ILIKE '%analyze%';
- 检查索引的健康状况:
SELECT schemaname, tablename, indexname, indexdef, pg_size_pretty(pg_relation_size(indexrelid)) AS index_size, idx_scan, -- 索引扫描次数 idx_tup_read, -- 从索引中读取的元组数 idx_tup_fetch -- 从索引中获取的元组数 FROM pg_stat_all_indexes WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY pg_relation_size(indexrelid) DESC;
- 手动执行 VACUUM 操作:
VACUUM mytable;
- 手动执行 VACUUM FULL 操作(谨慎使用):
VACUUM FULL mytable;
- 手动执行 ANALYZE 操作:
ANALYZE mytable;
- 重建索引:
REINDEX INDEX myindex;
- 重建表的所有索引:
REINDEX TABLE mytable;
- 修改 autovacuum 配置(全局):
ALTER SYSTEM SET autovacuum_max_workers = 5;
- 修改 autovacuum 配置(针对特定表):
ALTER TABLE mytable SET (autovacuum_vacuum_scale_factor = 0.1);
- 关闭 autovacuum(针对特定表):
ALTER TABLE mytable SET (autovacuum_enabled = false);
- 开启 autovacuum(针对特定表):
ALTER TABLE mytable SET (autovacuum_enabled = true);
- 禁用触发器:
ALTER TABLE mytable DISABLE TRIGGER ALL;
- 启用触发器:
ALTER TABLE mytable ENABLE TRIGGER ALL;
- 禁用外键约束:
ALTER TABLE mytable NOCHECK CONSTRAINT ALL;
- 启用外键约束:
ALTER TABLE mytable CHECK CONSTRAINT ALL;