批处理写入以及动态与参数化SQL,数据库的性能如何?

批处理写入是最有效的数据库优化之一。 批处理写入受大多数现代数据库和JDBC标准的一部分支持,并且受大多数JPA提供程序支持。

普通数据库访问包括在单独的数据库/网络访问中将每个DML(插入,更新,删除)语句发送到数据库。 每个数据库访问都有一定的开销,并且数据库必须独立处理每个语句。 批处理写入有两种形式,动态的和参数化的。 参数化是最常见的方法,通常可以带来最大的好处,因为动态可能存在解析问题。

要了解批处理编写,您必须首先了解参数化的SQL。 SQL执行由两部分组成,即解析和执行。 解析包括将字符串SQL表示形式转换为数据库表示形式。 执行包括在数据库上执行已解析的SQL。 数据库和JDBC支持绑定参数,因此SQL(数据)的参数不必嵌入到SQL中。 这避免了将数据转换为文本的成本,并允许重复执行同一SQL语句并执行多次。 这允许单个解析和多个执行,也称为“参数化SQL”。 大多数JDBC DataSource实现和JPA提供程序都支持参数化的SQL和语句缓存,这可以有效避免在运行的应用程序中进行解析。

动态SQL示例

INSERT INTO EMPLOYEE (ID, NAME) VALUES (34567, "Bob Smith")

参数化的SQL示例

INSERT INTO EMPLOYEE (ID, NAME) VALUES (?, ?)

参数化批处理编写涉及执行单个DML语句,但是具有用于多个同质语句的一组绑定参数,而不是用于单个语句的绑定参数。 这有效地允许数据库和网络将大批同质的插入,更新或删除作为单个操作而不是n个操作来处​​理。 数据库仅需要执行最少的工作,因为只有一条语句,因此最多只有一个解析。 它也与语句缓存兼容,因此根本不需要进行语句解析。 限制是所有语句的SQL必须相同。 因此,说插入1,000个Orders确实非常有用,因为每个Order的插入SQL都是相同的,只是bind参数不同。 但这对于插入1个订单或插入1个订单,1个OrderLine和1个客户没有帮助。 同样,所有语句必须是同一数据库事务的一部分。

动态批处理编写包括将一堆异构动态SQL语句链接到一个块中,然后通过单个数据库/网络访问将整个块发送到数据库。 这是有利的,因为只有一个网络访问权限,因此,如果数据库是远程的或通过慢速的网络访问,则可能会有很大的不同。 缺点是不允许参数绑定,并且数据库必须在接收到此庞大的SQL块时对其进行解析。 在某些情况下,解析成本可能超过网络收益。 另外,动态SQL与语句缓存不兼容,因为每个SQL都不相同。

JDBC通过其Statement和PrepareStatement批处理API(从JDBC 2.0开始,很早以前就是JDK 1.2)标准化了批处理写入。 JDBC批处理API需要不同的JDBC代码,因此,如果您使用的是原始JDBC,则需要重写代码以在批处理和非批处理API之间切换。 现在,大多数JDBC驱动程序都支持这些API,但是有些驱动程序实际上并不模拟DML批量发送DML到数据库。 那么,如何知道您是否真的正在批量编写? 唯一真正的方法是对其进行测试,并衡量性能差异。

JPA规范没有标准化批写配置,但是大多数JPA提供程序都支持它。 通常,通过持久性单元属性在JPA中启用批处理写入,因此打开或关闭它是一个简单的配置问题,并且不需要更改编码。 一些JPA提供程序在使用开放式锁定时可能不支持批处理写入,并且可能不对SQL进行重新排序以使其能够进行批处理,因此即使启用了批处理写入,您仍可能无法进行批处理写入。 始终在启用和禁用批写的情况下测试您的应用程序,并测量差异以确保其实际运行。

EclipseLink支持参数化和动态批处理编写(自EclipseLink 1.0起)。 在EclipseLink中,通过"eclipselink.jdbc.batch-writing"持久性单元属性启用批处理写入。 EclipseLink提供了三个选项: "JDBC""Buffered""Oracle-JDBC" 。 应始终使用"JDBC"选项。

"Buffered"用于不支持批量写入的JDBC驱动程序,并将动态SQL语句链接到单个块本身中。 "Buffered"不支持参数化的SQL,因此不建议使用。

"Oracle-JDBC"使用早于JDBC标准API的Oracle数据库JDBC API,现在已过时。 在EclipseLink 2.5之前,此选项允许在使用开放式锁定时进行批处理写入,但是现在常规的"JDBC"选项支持开放式锁定。

EclipseLink 2.5支持在所有(兼容)数据库平台上进行乐观锁定的批处理写入,而以前仅在选定的数据库平台上才支持。 EclipseLink 2.5还提供了一个"eclipselink.jdbc.batch-writing"查询提示,以禁止无法写入的本机查询(例如DDL或某些数据库平台上的存储过程)的批量写入。

EclipseLink通过"eclipselink.jdbc.bind-parameters""eclipselink.jdbc.cache-statements"持久单元属性来支持参数化SQL。 但是,通常不需要设置这些参数,因为参数绑定是默认设置,因此您只需将属性设置为禁用绑定即可。 默认情况下,语句缓存未启用,如果使用EclipseLink的连接池,则仅与EclipseLink相关;如果使用的是JDBC或Java EE DataSource,则必须在DataSource配置中配置语句缓存。

在EclipseLink中启用批量写入时,默认情况下它是参数化的批量写入。 要启用动态批处理写入,必须禁用参数绑定。 这与启用缓冲批写入相同。

支持批处理写入并不是很难,大多数JPA提供程序都支持这一点,对SQL进行排序以使其可以进行批处理是困难的部分。 在提交或刷新操作期间,EclipseLink会自动按表对SQL进行分组,以确保可以批处理同类的SQL语句(同时仍保持引用完整性约束并避免死锁)。 大多数JPA提供程序都不这样做,因此即使它们支持批处理写入,SQL的很多时间也无法从批处理中受益。

要在EclipseLink中启用批处理写入,请将以下内容添加到持久性单元属性;

"eclipselink.jdbc.batch-writing"="JDBC"

您还可以使用"eclipselink.jdbc.batch-writing.size"持久性单元属性来配置批处理大小。 默认大小为100。

"eclipselink.jdbc.batch-writing.size"="1000"

批处理非常依赖数据库,并且依赖JDBC驱动程序。 因此,我对与哪些数据库,它使用的驱动程序以及好处有兴趣。 我进行了两次测试,一个进行了50次插入操作,一个进行了100次更新操作(使用乐观锁定)。 我尝试了所有批处理写入选项,以及不使用任何批处理。

请注意,这不是数据库基准,我不是在相互比较数据库,而只是对自己进行比较

每个数据库都在不同的硬件上运行,有些是本地的,有些是跨网络的,因此不要将一个数据库与另一个数据库进行比较。 感兴趣的数据是使批写入相对于不使用批写入所带来的百分比收益。 对于插入测试,我还测量了使用参数化SQL与动态SQL以及不使用语句缓存的参数化SQL之间的差异。 结果是在10秒内处理的事务数(运行5次,并平均),因此,较大的数目是更好的结果。

驱动程序:MySQL-AB JDBC驱动程序版本:mysql-connector-java-5.1.22

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 483 0%
动态SQL,无批次 499 3%
参数化的SQL,无语句缓存 478 -1%
动态SQL,批处理 499 3%
参数化SQL,批处理 509 5%

更新测试

选项 平均结果 与非批次的百分比差异
参数化SQL 245 0%
动态SQL,批处理 244 0%
参数化SQL,批处理 248 1%

因此,结果似乎表明批处理写入没有任何影响(5%在方差之内)。 这的真正含义是,MySQL JDBC驱动程序实际上并不使用批处理,它只是模拟JDBC批处理API,并在其下逐个执行语句。

尽管MySQL确实具有批处理支持,但它只需要不同的SQL。 MySQL JDBC驱动程序确实支持此功能,但是需要设置rewriteBatchedStatements=true JDBC连接属性。 可以通过修改您的连接URL轻松地进行设置,例如;

jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true

MySQL:rewriteBatchedStatements = true

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 504 0%
动态SQL,无批次 508 0%
参数化的SQL,无语句缓存 483 -4%
动态SQL,批处理 1292 156%
参数化SQL,批处理 2181 332%

更新测试

选项 平均结果 与非批次的百分比差异
参数化SQL 250 0%
动态SQL,批处理 669 167%
参数化SQL,批处理 699 179%

因此,如果配置正确(似乎JDBC驱动程序默认不执行此操作,我不知道),那么批处理写入确实会在MySQL中产生很大的不同。 参数化批处理写入效果最佳,插入速度快332%,更新速度快179%。 动态批处理写入效果也很好。 有趣的是,MySQL上的动态SQL和参数化SQL之间似乎没有什么区别(我猜想MySQL解析的速度确实更快,或者对预准备语句的优化很少)。

PostgreSQL 8.4 JDBC4

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 479 0%
动态SQL,无批次 418 -12%
参数化的SQL,无语句缓存 428 -10%
动态SQL,缓冲 1127 135%
动态SQL,批处理 1127 135%
参数化SQL,批处理 2037 325%

更新测试

选项 平均结果 与非批次的百分比差异
参数化SQL 233 0%
动态SQL,批处理 395 69%
参数化SQL,批处理 707 203%

结果表明,批写在PostgreSQL上有很大的不同。 参数化批处理写入性能最佳,插入速度快325%,更新速度快203%。 动态批处理写入效果也很好。 对于PostgreSQL,我还评估了EclipseLink的缓冲批处理写入的性能,该性能与动态JDBC批处理写入的性能相同,因此我假设驱动程序在做相同的事情。 参数化的SQL优于动态SQL约10%,但不带语句缓存的参数化SQL与动态SQL相似。

Oracle JDBC驱动程序版本:11.2.0.2.0

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 548 0%
动态SQL,无批次 494 -9%
参数化的SQL,无语句缓存 452 -17%
动态SQL,缓冲 383 -30%
动态SQL,批处理 489 -10%
参数化SQL,批处理 3308 503%

更新测试

选项 平均结果 与非批次的百分比差异
参数化SQL 282 0%
动态SQL,批处理 258 -8%
参数化SQL,批处理 1672 492%

结果表明,参数化批处理写入对Oracle产生了很大的影响,插入速度快503%,更新速度快492%。 动态批处理写入没有任何好处,这是因为Oracle的JDBC驱动程序仅模拟动态批处理并逐个执行语句,因此它具有与动态SQL相同的性能。 缓冲批写入实际上比根本不批处理具有更差的性能。 这是因为巨大的动态SQL块的解析成本,这在不同的配置中可能会有所不同,如果数据库是远程的或跨慢速的网络,则我会看到这样做的好处。

带有语句缓存的参数化SQL比动态SQL提供约10%的收益,并指出,要从参数化中受益,您需要使用语句缓存,否则性能可能会比动态SQL差。 粗略地讲,参数化SQL还有其他好处,因为它从服务器中删除了CPU处理,这在单线程情况下可能无济于事,但在数据库是瓶颈的多线程情况下,可能会产生很大的不同。

(本地)

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 3027 0%
动态SQL,无批次 24 -99%
参数化的SQL,无语句缓存 50 -98%
动态SQL,批处理 24 -99%
参数化SQL,批处理 3252 7%

更新测试

选项 平均结果 与非批次的百分比差异
参数化SQL 1437 0%
动态SQL,批处理 6 -99%
参数化SQL,批处理 2172 51%

结果表明,参数化批处理写入对Derby有所不同,插入速度快7%,更新速度快51%。 由于我的数据库是本地数据库,因此结果差异不如其他数据库那么大。 对于网络数据库,这将是一个更大的差异,但这确实表明,即使对于本地数据库,批处理写入也可以带来好处,因此,这不仅仅是网络优化。 Derby真正有趣的结果是动态和非缓存语句的可怕性能。 这表明Derby具有巨大的解析成本,因此,如果您使用的是Derby,那么将带参数的SQL与语句缓存一起使用非常重要。

用于JDBC和SQLJ的IBM数据服务器驱动程序版本:4.0.100

结果基本上与Oracle类似,因为参数化的批处理编写具有很大的性能优势。 动态批处理写入的性能较差,因此无法使用参数化SQL进行批处理,而动态SQL和未使用语句缓存的参数化SQL会导致性能降低。

Microsoft SQL Server JDBC驱动程序2.0版本:2.0.1803.100

结果类似于PostgreSQL,显示参数化和动态批处理编写均提供了显着的好处。 参数化批处理编写性能最好,参数化SQL优于动态SQL,并且没有语句缓存。

**更新**

有人要求我也测试H2和HSQL,所以这里是结果。

(本地)

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 4757 0%
动态SQL,无批次 3210 -32%
参数化的SQL,无语句缓存 4757 0%
动态SQL,缓冲 1935年 -59%
动态SQL,批处理 3293 -30%
参数化SQL,批处理 5753 20%

结果表明,通过参数化批处理写入,H2的执行速度提高了20%。 H2是一个内存数据库(由持久日志文件支持),因此预期不会受益于不涉及任何网络的情况。 动态批处理编写和动态SQL执行的参数化SQL更差。 有趣的是,将参数缓存与参数化SQL一起使用不会产生任何区别。 我的假设是H2始终在其连接中缓存准备好的语句,因此用户不需要自己进行语句缓存。

(本地)

插入测试

选项 平均结果 与非批次的百分比差异
参数化SQL,无批处理 7319 0%
动态SQL,无批次 5054 -30%
参数化的SQL,无语句缓存 6776 -7%
动态SQL,批处理 5500 -24%
参数化SQL,批处理 9176 25%

结果表明,通过参数化批处理编写,HSQL的执行速度提高了25%。 HSQL是一个内存数据库(由持久日志文件支持),因此期望它不会像没有网络一样受益。 动态批处理编写和动态SQL执行的参数化SQL更差。

参考: 批处理以及动态和参数化SQL,数据库的性能如何? Java持久性性能博客中来自我们JCG合作伙伴 James Sutherland的内容。

翻译自: https://www.javacodegeeks.com/2013/09/batch-writing-and-dynamic-vs-parametrized-sql-how-well-does-your-database-perform.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367302.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android音量图标不见了,电脑声音图标不见了如何解决?

最近有电脑用户反映,看视频时觉得声音太小了,要调大点声,却发现任务栏上的声音图标不见了,想调个声音都难。那么,电脑声音图标不见了如何解决呢?我们一起往下看看。方法步骤一、XP系统下找回任务栏上的声音图标1、重启…

认识iOS系统架构

关于本文: 文章主要介绍iOS系统架构中的四层结构的内容、常用的框架、大致的功能,然后对iOS开发人员的发展提出自己的一些拙见。 一、iOS系统是基于UNIX系统,所有从系统稳定性上来说的确比其他操作系统的产品要好。 iOS在系统架构上分为4层&a…

r语言赋值为na_r语言将空白格替换成NA

有数据集类似user_id qid1371 000013046dc0ab29ef8773eb61aba623 02 0000cfcadfa43ef824669405081165b13 0006ee1acc5321260ba0fbff1fb8f6494 00083f7b8c6170a3fc976d7b99245259 …

Java泛型教程–示例类,接口,方法,通配符等

泛型是Java编程的核心功能之一,它是Java 5中引入的。如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它。 在集合类中使用泛型非常容易,但是它提供了比仅创建集合类型更多的功能,我们将在本文中…

html5中音乐播放器怎么写,打造属于自己的音乐播放器 HTML5之audio标签

我的音乐播放器HTML5中增加了Audio和Video标签,这两个标签的用法非常相似。功能却是相当强大,我们先来看一下Audio标签各个浏览器的支持情况。这里用的依然是Can I Use这个在线网站,相信学习前端的同学应该都不陌生。Can I Use我们可以看到&a…

初识react(四) react中异步解决方案之 redux-saga

回顾 初识react(一) 揭开jsx语法和虚拟DOM面纱初识react(二) 实现一个简版的html redux.js的demo初识react(三)在 react中使用redux来实现简版计数器初识react(四) react中异步解决方案之 redux-saga初识react(五) 数据流终极解决方案 dva(零配置) 今天demo是实现一个异步的计…

C# WinFrom 关于MDI

dev是一个牛B 到没边的控件 我们正常用winform做个原始mdi窗体 一点都不好看 但 用的dev只需要一个控件 就可让显示舒服多了 建一个项目 上边放一个 xtraTabbedMdiManager1 一个button1 button1.click如下: Form frm new Form(); frm.MdiParent this; frm.Text &…

Jfinal 文件上传

JFinal上传文件 uploadify 可以在http://www.uploadify.com/ 下载。 在原项目的基础上。 uploadify使用&#xff1a; <input id"file_upload_1" name"file_upload" type"file" multiple"true"> /** param uploader 文件上传方法…

轻量级的开源集成:Apache Camel还是Spring集成?

首先&#xff0c;为全面披露信息&#xff0c;在过去的1.5年中&#xff0c; 我一直担任 FuseSource&#xff08;现为Red Hat&#xff09; 的顾问&#xff0c;为零售&#xff0c;运输&#xff0c;银行/金融等不同行业的大型和小型公司提供SOA和集成项目支持。我的专长是使用该领域…

blue html中转换,Vue/Vue中Html和Markdown互相转换/README.md · bluemoon/LearningNotes - Gitee.com...

# Vue中Html和Markdown互相转换## 前言最近想实现的一个功能&#xff0c;就是将系统中的博客进行导出成Markdown格式&#xff0c;后面经过了调研发现有两种方法能够满足需求&#xff0c;一个是Java后台中将HTML转换成Markdown&#xff0c; 然后导出。第二种方式是在客户端将Htm…

WePY:在质疑中前进 | 文末福利

WePY 作者介绍 Q: 先介绍一下自己吧~ Gcaufy: 我 2011 年大学毕业之后&#xff0c;阴错阳差的走上了 Web 开发的道路。15 年之前算是自由职业 SOHO 工作&#xff0c;主要给一些国外的大公司做外包系统&#xff0c;更多的是做后端开发。15 年之后以前端工程师的身份加入腾讯&a…

表单必填标星_怎么用JS做form表单验证,要详细代码,求救!(带星号的是必填项)...

匿名用户1级2014-06-17 回答举个例子吧&#xff1a;<input type”text” id”telephone” ><input type“button” οnclick“functioncheck1”value“检测”>如果要检测它是否符合标准&#xff0c;那我就会在页面中导入js包然后写一个<script> f…

MySQL/MariaDB表表达式(3):视图

视图是表表达式的一种&#xff0c;所以它也是虚拟表。对视图操作的时候会通过语句动态的从表中临时获取数据。 1.创建、修改视图 CREATE [OR REPLACE][ALGORITHM {UNDEFINED | MERGE | TEMPTABLE}]VIEW [IF NOT EXISTS] view_name [(column_list)]AS select_statement[WITH [C…

使用Arquillian(包括JPA,EJB,Bean验证和CDI)测试Java EE 6

很长时间以来&#xff0c;我听到很多人对Arquillian说好话 。 虽然我一直在阅读有关其用法的文章&#xff0c;但实际上我无法在一篇文章中找到涵盖我认为重要的某些方面的文章。 当然&#xff0c;我看起来还不够努力。 我要讲的要点是&#xff1a; 使用JPA。 我只是在这里使用…

xpath和css selector

参考&#xff1a;https://www.cnblogs.com/captainmeng/p/7852044.html css selector解释&#xff1a;https://www.cnblogs.com/feng0815/p/8367672.html 转载于:https://www.cnblogs.com/Mezhou/p/9671284.html

android任务书技术要求,毕业设计任务书-Android应用程序开发

* *大学信息工程学院毕业设计(论文)任务书指导教师&#xff1a;*** 职称&#xff1a;讲师学生人数&#xff1a; 3学生姓名(学号、专业)&#xff1a;刘**(200927030111 09信息管理)***(200927030120 09信息管理)李**(200927030107 09信息管理)毕业设计(论文)题目(来源、类型)And…

Event Loop 其实也就这点事

前段时间在网上陆续看了很多关于 Event loop 的文章&#xff0c;看完也就混个眼熟&#xff0c;可能内心深处对这种偏原理的知识有一些抵触心情&#xff0c;看完后也都没有去深入理解。最近在看 Vue 的源码&#xff0c;在读到关于 nextTick 的实现时&#xff0c;总有一种似曾相识…

mock模拟接口测试 vue_在 Vue-CLI 中引入 simple-mock实现简易的 API Mock 接口数据模拟...

在 https://www.jb51.net/article/151520.htm这篇文章中&#xff0c;我们介绍了在 Angular-CLI 中引入 simple-mock 的方法。本文以 Vue-CLI 为例介绍引入 simple-mock 实现前端开发数据模拟的步骤。本质上这里介绍的是在 webpack-dev-server 中配置 simple-mock 实现 API Mock…

Kudu系列: Kudu主键选择策略

每个Kudu 表必须设置Pimary Key(unique), 另外Kudu表不能设置secondary index, 经过实际性能测试, 本文给出了选择Kudu主键的几个策略, 测试结果纠正了我之前的习惯认知. 简单介绍测试场景: 表中有一个unqiue字段Id, 另外还有一个日期维度字段histdate, 有三种设置kudu PK的方法…

OSS网页上传和断点续传(OSS配置篇)

OSS网页上传和断点续传主要根据BrowserJS-SDK和相关文档整理而得&#xff0c;快速构建OSS上传应用 一、Bucket设置 浏览器中直接访问OSS需要开通Bucket的CORS设置 将allowed origins设置成 *将allowed methods设置成 PUT, GET, POST, DELETE, HEAD将allowed headers设置成 *将e…