PreparedStatement
- 使用占位符,一次解析多次执行,可提高性能
- 可防止SQL注入
- 可缓存的PS,可提高性能
- 需要数据库服务端支持
Batch操作
- 一次IO提交多条sql语句
- 减少IO次数,提高性能
Mysql和Oracle是否使用预编译的思考
Mysql(mysql 5.7.20和mysql-connector-java-8.0.15.jar)
- 基于同一连接,一次解析多次执行,jdbc driver实现可缓存PS
- 以前的版本默认useServerPrepStmts=true,5.0.5以后的版本默认useServerPrepStmts=false mysql jdbc默认不开启PreparedStatement,收到的sql已经是替换成具体值的Sql.此时使用PS Batch 等同于普通的Sql Batch操作
- useServerPrepStmts=true:服务端启用预编译机制,客户端(jdbc driver)只要不close掉statement,该statement可以多次重复使用,而不用再执行prepareStatement
- cachePrepStmts=true:客户端(jdbc driver)close掉statement时,不会真的close,而是放connection缓存里。后续客户端只要不close掉connection,那么客户端即使再调用了prepareStatement,也是使用之前客户端缓存的客户端。有点类似PreparedStatementCache,但PSCache是从数据库连接池框架(druid的maxOpenPreparedStatements,BoneCP的statementsCacheSize,c3p0的maxStatementsPerConnection)层面上来讲,而此处指的是jdbc driver层面。
- statement执行close方法时才会放入缓存,如果close之前,同样sql语句多次调用了prepareStatement方法,则会返回多个无关的statement,客户端在依次close掉这些statement时,只会缓存其中的一个statement,其它会被回收掉。这也证明mysql服务端不会做任何缓存或者唯一之类的处理,只会纯粹的做预编译处理,然后返回statement_id给客户端。
- 一次编译多次执行,指的是数据库服务器端做一次预编译处理,客户端可以多次使用statement对象与服务器进行交互。
- rewriteBatchedStatements=true:mysql自身实现的批量操作方法(转换成muti value的方式),性能是最好的,因为它是一次io,一次解析执行,由于此时占位符个数应该是不定的,不建议使用服务端预编译机制,更不建议客户端缓存,需要注意一次批量的包大小。
- max_allowed_packet: 需要确定服务端该配置的大小,单个包超过该值会抛异常
- autoGenerateTestcaseScript=true&traceProtocol=true: 可以在jdbc driver端看到与服务端的交互日志
- show variables like '%log%';set global general_log=on;show variables like 'general_log_file' 可以查看服务端sql日志
Mysql PS 执行详细参考
Oracle待续
- oracle jdbc driver未开源,其原理资料并不多,其默认就支持预编译,详细交互不是很清楚
- oracle服务端的预编译应该全局性的,而不是单个连接范围内的
- 客户端机制应该没太多特殊性,同mysql类似
Oracle JDBC Developer's Guide
引用参考https://blog.csdn.net/theorytree/article/details/7331096
oracle执行sql过程
oracle sql执行顺序
oracle里面除了查询结果集缓存外,还有SQL缓存,缓存在SGA共享区域,可以使用软解析,而跳过更解析。
语句缓存的好处
• ORACLE执行SQL语句时,先将SQL语句的字串通过一个哈希算法得出一个哈希值,然后检查共享池中是否已存在这个哈希值,若有就用已缓存的执行计划来执行这个语句(CACHE HIT 缓存命中),若没有(CACHE MISS 缓存缺失)则需进行解析,解析需要完成下面的工作:
Ø 语法检查;
Ø 语义检查,看参考对象是否存在,类型是否正确;
Ø (如果是CBO优化模式)收集参考对象的统计;
Ø 检查用户的权限是否足够;
Ø 从许多可能的执行路径中选择一条作为执行计划;
Ø 生成语句的编译版本(P-CODE)。
• 解析是一个昂贵的操作,因为过程中需要消耗许多资源;
• 最大化CACHE HIT是调整共享池的目标