返回

用一次update慢sql的优化经验告诉你有经验的 DBA 和没经验 DBA 的区别有多大

后端





最近,线上的ETL数据归档SQL发生了点问题,有一个UPDATE SQL跑了**两天** 还没跑出来:

UPDATE t_retailer_order_record
SET archive_flag = 1
WHERE order_create_time < '2016-01-01 00:00:00'
AND archive_flag = 0;


这个SQL其实就是将`t_retailer_order_record``archive_flag`为0且`order_create_time`小于2016-01-01 00:00:00的数据的`archive_flag`置为1,看起来非常简单的一个SQL,怎么会跑这么久呢?

**一、分析SQL语句本身** 

首先,我们先来分析一下这个SQL语句本身。

1. **全表扫描** :
   这个SQL语句没有使用任何索引,所以它会对`t_retailer_order_record`表进行全表扫描,这是非常耗时的。
2. **没有过滤条件** :
   这个SQL语句没有使用任何过滤条件,这意味着它会更新所有满足条件的数据,这也非常耗时。
3. **更新大量数据** :
   这个SQL语句需要更新大量的数据,这也是导致它运行缓慢的原因之一。

**二、使用索引** 

既然我们已经分析出了这个SQL语句的性能瓶颈,那么我们就可以针对这些瓶颈进行优化。

首先,我们可以给`t_retailer_order_record`表添加一个索引,这个索引可以是`order_create_time`字段上的索引,也可以是`archive_flag`字段上的索引。添加了索引之后,SQL语句就可以使用索引来快速查找数据,从而提高执行效率。

CREATE INDEX idx_order_create_time ON t_retailer_order_record (order_create_time);
CREATE INDEX idx_archive_flag ON t_retailer_order_record (archive_flag);


**三、调整参数** 

除了使用索引之外,我们还可以通过调整参数来提高SQL语句的执行效率。

我们可以将`innodb_buffer_pool_size`参数调大,这样可以使更多的索引数据被缓存在内存中,从而减少磁盘I/O,提高SQL语句的执行效率。

innodb_buffer_pool_size=16G


我们还可以将`innodb_io_capacity`参数调大,这样可以提高数据库的I/O吞吐量,从而加快SQL语句的执行速度。

innodb_io_capacity=2000


**四、最终效果** 

经过以上优化之后,这个SQL语句的执行时间从两天减少到了几秒钟,大大提高了SQL语句的执行效率。

**五、总结** 

通过这次优化经验,我们可以总结出以下几点:

1. **分析SQL语句本身** :
   在优化SQL语句之前,我们首先要分析一下SQL语句本身,找出SQL语句的性能瓶颈。
2. **使用索引** :
   如果SQL语句没有使用索引,那么我们可以给表添加一个索引,这样可以提高SQL语句的执行效率。
3. **调整参数** :
   我们可以通过调整参数来提高SQL语句的执行效率,比如我们可以将`innodb_buffer_pool_size`参数调大,这样可以使更多的索引数据被缓存在内存中,从而减少磁盘I/O,提高SQL语句的执行效率。

希望这篇文章对大家有所帮助,感谢阅读!