tidb如何批量提高update执行效率

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tidb如何批量提高update执行效率相关的知识,希望对你有一定的参考价值。

参考技术A 具体如下:
尝试使用merge into,执行计划的cost值仅为134685,2分种执行完成,效率大大提升。
merge into语法:
merge into table1 A
using (select column1,column2, from table2) B
on (a.column1=b.column1 and )
when matched then
update set a.column2=b.column2,a.column3=b.column3;

hibernate的update及JDBC数据库批量操作

最本质的区别是Session.update()更新的实体。而Query.update()更新的是执行SQL语句。
由此会带来一些问题。

性能问题

首先如果要使用Session去更新数据库需要执行一个获取实体的操作,也就是说需要先获取这个实体。而如果执行Query.update()则是直接执行SQL语句(或者HQL)。
本来以我的理解来看Query的效率应该比Session效率要高的,因为Query.update()更加原生,但是后来实现以下发现这个不一定。

首先,一般来说我们使用Query.update()不会直接构造一个Query区执行,因为软件中为了方便使用常常把Query.updata()包装成一些比较方便的方式,比如根据所给的class类型以及where的相关参数去生成Query所以这样更方便使用,这个过程也很麻烦。所以Query为了方便使用,效率有一定损失。比如我实测这两个方法使用相同的策略。但是使用生成Query形式的方式,10000次操作下Query.update()需要2min14s,而Session.update()则只需要使用1min19s。

批量操作

然后我又查了一下hibernate的批量操作的问题。
主要参考了这篇文章
Hiberante批量更新缺点及解决方案
Hibernate批量操作技巧

第一篇文章主要的观点在于两点:

以上批量更新方式有两个缺点:
(1)占用大量内存,必须把1万个Customer对象先加载到内存,然后一一更新它们。
(2)执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必须通过1万条update语句才能更新一万个Customer对象,频繁的访问数据库,会大大降低应用的性能。

第一个缺点的可以通过session的flush和evict来尽可能提早释放Customer。
第二个缺点没有办法解决,作者推荐直接使用JDBC API来实现。或者使用储存过程来做实现更快。

第二篇文章主要在讨论如何在hibernate来尽可能实现快速批量操作

主要通过flush和设置batch_size来实现。

Statement、preparedStatement和CallableStatement的区别
主要参考了这两篇文章:

Statement、preparedStatement和CallableStatement的区别
主要观点:

Statement 每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement.

PreparedStatement是预编译的,使用PreparedStatement有几个好处
a. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
b. 安全性好,有效防止Sql注入等问题。
c. 对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;
d. 代码的可读性和可维护性。

CallableStatement接口扩展 PreparedStatement,用来调用存储过程,它提供了对输出和输入/输出参数的支持。CallableStatement 接口还具有对 PreparedStatement 接口提供的输入参数的支持。

但是按照目前的资料来看我对PreparedStatement和CallableStatement之间有什么区别。大概可以总结如下:

  • 首先CallableStatement是继承自PreparedStatement的。
  • PreparedStatement主要来数据库支持预编译就可以了,而CallableStatement则需要数据库支持存储过程才行。
  • 从执行效率来说CallableStatement要比PreparedStatement效率要高。
  • 对于PreparedStatement只要在编程语言中定义就好了,而对于CallableStatement还需要在编程语言中预先写好存储过程才行。

另外一些疑问:

  • 有一些说法是PreparedStatement就是存储过程,但是个人来说不太支持这种说法。我猜想可能是早起JDBC和存储过程版本支持问题。个人还是觉得CallableStatement的实现。
  • 另外一个问题就是PreparedStatement的预处理过程是经过缓存的。这里的缓存策略是一个问题,比如缓存何时刷新,是由数据库刷新还是可以程序控制之类的。目前还没有找到资料。

以上是关于tidb如何批量提高update执行效率的主要内容,如果未能解决你的问题,请参考以下文章

hibernate的update及JDBC数据库批量操作

hibernate的update及JDBC数据库批量操作

如何提高效率SQLite大数据量操作效率

提高python执行效率的方法?

如何提高批量插入效率?

ARM流水线如何提高代码执行效率