SQL 清空表:性能优化技巧

TRUNCATE 是清空表的最快方法。
记住这一点。

TRUNCATE直接删除,比DELETE快几十倍。
但有一个障碍,不能有外键。
通过设置参数可以绕过MySQL。

DELETE需要逐行删除,速度很慢。
使用外键链接表会减慢速度,但禁用外键可以加快速度。

事务封装是个好东西,失败了还可以回滚。
金融体系需要利用这一点。

批量删除大量数据。
一次删除 1 0,000 行并使用脚本运行它。
不要继续发送,否则 I/O 会爆炸。

清空表后必须重建索引。
否则查询会很慢。
忘记简单的结构吧。

避开繁忙时间,别被骂。
这取决于执行计划并使用 EXPLAIN 命令。
如果参数调整得好,内存会更大,速度会更快。

MySQL TRUNCATE 是不可逆的。
Oracle 清除后无法更改它。
SQL Server 权限必须足够。

找出最适合您的一个。
首先尝试截断。

mysql 表 删除数据

等等,昨晚我还在想这个问题。
记得上周三在公司加班到十点,就是为了满足一个客户的数据清理需求。
当时表中大约有5 0万条记录,客户表示只需删除状态为“过期”的订单即可。
我使用了子查询,结果挂了将近二十分钟,屏幕不停地旋转。
最后,我赶紧开了一个交易,先尝试删除三项,看看是否有问题,然后才全部删除。
我还截断了一些临时表。
这时我才意识到,听起来很简单,但实际做的时候却要小心。
您提到子查询会影响性能。
我认为 5 0 万件商品并不是特别大。
具体什么情况会导致这样的问题呢?

MySQL的分区删除操作详解mysql中删除分区语法

MySQL分区删除操作...需要把这件事解释清楚。
2 02 2 年,我面对一张百万数据的巨大表,运行速度极其缓慢。
数据按月划分。
例如,订单_2 02 2 _01 、订单_2 02 2 _02
想一想,分段是为了速度。
当执行查询时,MySQL 知道在哪个分区中查找数据,而无需扫描整个表。
但随着时间的推移,分区可能会包含无用的数据。
例如,不再需要检查order_2 02 2 _01 此时应将其除去。

如何删除它?
一种方法是全局删除它。
您使用WHERE条件直接从表中删除;像这样写。
例如,DELETE FROM order_2 02 2 _01 WHERE status='Cancelled';它将删除2 02 2 年1 月所有已取消的订单。
无论数据在哪个分区,满足条件时都会被删除。

另一种方法是删除单个分区。
这取决于分区类型。
如果是范围分区,比如byage、byrange(age)分区(分区p0值小于2 0,...),可以使用delete(partitionname)fromtablepartitionwhere条件;例如,要删除年龄小于 2 0 的订单,请使用 DELETE FROM order_2 02 2 _01 PARTITION p0 WHERE Age < 2>
但是请注意!如果是hash分区,比如PARTITION BY HASH(id)...,MySQL不支持单个分区删除。
如果使用DELETE PARTITION,会报错。
哈希分区的数据分布是随机的,没有办法指定删除哪个分区。

我给你举一个具体的例子。
假设有一张表sales_data,与季度相关除以:
sql 创建表 sales_data ( ID INT 自动递增主键, 金额小数(1 0,2 ), sale_date 日期 ) 按范围分区 (Year(Sale_Date)) ( 分区p2 02 1 的值小于2 02 2 , 分区 p2 02 2 的值小于 2 02 3 );
现在你想删除2 02 1 年的所有销售记录然后使用全局删除:
sql 从 sales_data 中删除,其中年份(sales_date)= 2 02 1 ;
如果只想删除2 02 1 年第2 季度的数据(假设是4 月1 日到6 月3 0日),范围分区可以如下:
sql 从分区页 2 02 1 中删除 sales_data,其中 sales_date 介于“2 02 1 -04 -01 ”和“2 02 1 -06 -3 0”之间;
但如果是hash分区,就不能使用DELETE PARTITION,只能使用GLOBAL DELETE。

注释:
1 单个分区删除仅适用于范围分区,哈希不起作用。
2 . 删除数据会将数据移动到分区,这可能会影响性能。
如果分区表很大,删除之前最好先备份。
2 02 2 年,我花了几个小时删除了千万级别的分区表。
删除后,查询确实很快,但占用 CPU 时间很长。
3 、删除数据时要小心,不要误删。
比如我之前删除了一个分区,但是条件写错了,2 02 3 年的数据也被删除了。
那是一场灾难。

简而言之,从分区表中删除数据取决于分区类型。
Range分区可以单独删除,而hash分区只能全局删除。
删除前请做好备份,请勿握手。

mysql如何优化delete语句性能

说实话,优化MySQL中DELETE语句的性能对于我来说已经是很长一段时间的常事了。
经过这么多年,我总结了一些成果,下面与大家分享。

首先我们来谈谈WHERE子句。
这个东西如果不用索引那就悲剧了。
全表扫描的效率极低。
我记得有一次,我的一位朋友因为没有建立索引而不得不删除数百万条数据。
结果,处理器和硬盘几乎被烧毁。
因此,我建议在WHERE子句中的列上创建适当的索引,例如主键、唯一索引或复合索引。
另外,不要对条件中的字段进行函数操作,例如直接写WHERE YEAR(create_time)=2 02 3 这个东西需要重写为 WHERE create_time BETWEEN '2 02 3 -01 -01 ' AND '2 02 4 -01 -01 '。
请务必使用 EXPLAIN 检查执行计划以查看索引是否正在使用。

此外,批量删除也很重要。
一次性删除太多数据,增加事务大小,会导致undo和重新注册时间过长,事务过长,锁等待严重,甚至可能造成主从之间的延迟。
我已经遇到过这种情况。
有一次,我在处理千万级数据的删除时,直接用DELETE来管理。
结果,系统死机了几个小时。
我建议使用LIMIT进行批量删除,例如每次删除1 000到5 000行,然后在应用程序级循环中进行,直到受影响的行数变为0。
可以在每个批次之间进行短暂休息,例如Sleep(0.1 ),这可以减少主从复制的负载。

我们来谈谈 TRUNCATE 和删除分区。
TRUNCATE 清除整个表的速度比 DELETE 快得多,因为它不写入行级日志,并且可以重置自增 ID。
如果需要彻底清除表数据,请使用TRUNCATE。
不过重建表也是一个不错的选择,特别是当您需要保存少量数据时。
您可以创建一个新表,插入所需的数据,然后交换新旧表的名称。

配置 InnoDB 设置也很重要。
正确配置 InnoDB 设置可以减少删除过程中的 I/O 和日志记录开销。
例如,您可以暂时增加 innodb_buffer_pool_size 以提高缓存命中率。
设置 innodb_flush_log_at_trx_commit=2 以减少磁盘刷新频率。
如果这只是临时操作,您还可以禁用二进制日志记录。

您还应该注意检查外键约束。
如果一个表有外键关联,每次DELETE都会检查子表,导致性能不佳。
因此,除非需要外键约束或者并发程度较高的场景,可以考虑应用层来维护一致性。
如果您需要暂时禁用外键检查,请务必首先保护您的数据。

最后,对于按照时间等维度分区的表,使用分区可以显着提高删除效率。
例如,可以按日期对表进行分区,删除旧数据时直接DROPPARTITION。

总之,优化DELETE语句性能的关键在于细节。
您应该注意索引、批量删除、TRUNCATE、分区表、InnoDB 参数和外键约束检查。
当然,在实际使用之前,一定要在测试环境中进行测试,以免影响生产环境。