精华帖 (2) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2007-01-24
刚才查了一下,MySQL Connector/J Docs 中确实有写到:
引用 PreparedStatement
PreparedStatements are implemented by the driver, as MySQL does not have a prepared statement feature. Because of this, the driver does not implement getParameterMetaData() or getMetaData() as it would require the driver to have a complete SQL parser in the client. Starting with version 3.1.0 MySQL Connector/J, server-side prepared statements and binary-encoded result sets are used when the server supports them. 所以我在想,是不是在建立MySQL的JDBC连接时,对Driver中PreparedStatement相关属性(例如cachePrepStmts)的配置应该会对将来的性能有不小的影响? |
|
返回顶楼 | |
发表时间:2007-01-24
robbin 写道 是的,你们确实做了无用功。测试的目的在于指导实践。就单个请求来说statement要快,但是如果按照这种思路去写代码,后果是很严重的。因为会对数据库服务器造成很重的压力,系统吞吐量也要降低。早在2001年的时候,我维护的一个系统(访问量巨大,每天上百万),Oracle数据库每周都要宕机一次,经过几个月的排查,最终找到的原因就是我们程序所有的条件查询全部都是statement拼SQL字符串。全部改掉以后恢复正常,性能也明显提高。
实际的应用程序都是多用户并发的web应用,不是单机自己一个人用的,你们那种测试根本就不能反应实际的多用户并发的系统吞吐量和数据库负载情况,不是误导是什么? 我想,你的这个经验是在oracle上得到的,我在Oracle上也得到了相同的经验,(我在前面的帖子中提及了), 但是,每个数据库是不同的,特别是,MySQL数据库本身并没有PreparedStatemet特性,这一点可以从MySQL JDBC Driver的reference里查到,所以至少,在MySQL上使用PreparedStatement在理论上就没有任何优势,更甚的是, 从我们的测试来看,在MySQL上使用PreparedStatement会比Statement慢一倍左右。 你不认为,了解到不同数据库在这一点上有着较大的差别,是有意义的么? |
|
返回顶楼 | |
发表时间:2007-01-24
我在 Oracle 下的测试结果:
数据库: Oracle9i Enterprise Edition Release 9.2.0.1.0 jdbc驱动 : ojdbc14.jar 数据库表结构脚本: create table STMTUSER ( USERNO NUMBER default 0 not null, USERNAME VARCHAR2(40) default '无名无名无名无名' not null, EMAIL VARCHAR2(100) default 'abcdefg@gmail.com' not null, PHONE VARCHAR2(21) default '1388888888888' ) ; alter table STMTUSER add constraint PK_STMTUSER_USERNO primary key (USERNO); 主键序列: create sequence SEQ_STMTUSER_ID minvalue 1 maxvalue 999999999999999999999999999 start with 100021 increment by 1 cache 20; 生成测试数据的sql: insert into stmtuser (userno) values(SEQ_STMTUSER_ID.Nextval); 共生成10万条数据. 在plsql中查看会话观察到的 Statement执行的sql为: select t.*, t.rowid from stmtuser t where t.userno= 3277 (变化的数字) select t.*, t.rowid from stmtuser t where t.userno= :1 (使用的占位符) 第一轮测试, Statement和PreparedStatement各创建一个连接. 循环内每次创建stmt,并关闭stmt 第一次: 执行 500 次Statement操作耗费的时间为3594 执行 500 次PreparedStatement操作耗费的时间为3125 第二次: 执行 5000 次Statement操作耗费的时间为17985 执行 5000 次PreparedStatement操作耗费的时间为12625 第三次: 执行 50000 次Statement操作耗费的时间为154094 执行 50000 次PreparedStatement操作耗费的时间为113188 第二轮测试,Statement和PreparedStatement各创建一个连接.各只创建一次stmt 第一次: 执行 500 次Statement操作耗费的时间为2875 执行 500 次PreparedStatement操作耗费的时间为938 第二次: 执行 5000 次Statement操作耗费的时间为19453 执行 5000 次PreparedStatement操作耗费的时间为6031 第三次: 执行 50000 次Statement操作耗费的时间为155250 执行 50000 次PreparedStatement操作耗费的时间为43891 附件是测试的 java 文件: |
|
返回顶楼 | |
发表时间:2007-01-24
引用 In Embedded SQL, dynamic statements are SQL statements that need to be compiled at runtime, rather than statically. Typically, dynamic statements contain input parameters, although this is not a requirement. In SQL, the prepare command is used to precompile a dynamic statement and save it so that it can be executed repeatedly without being recompiled during a session. If a statement is used multiple times in a session, precompiling it provides better performance than sending it to the database and compiling it for each use. The more complex the statement, the greater the performance benefit.If a statement is likely to be used only a few times, precompiling it may be inefficient because of the overhead involved in precompiling, saving, and later deallocating it in the database.Precompiling a dynamic SQL statement for execution and saving it in memory uses time and resources. If a statement is not likely to be used multiple times during a session, the costs of doing a database prepare may outweigh its benefits. Another consideration is that once a dynamic SQL statement is prepared in the database, it is very similar to a stored procedure. In some cases, it may be preferable to create stored procedures and have them reside on the server, rather than defining prepared statements in the application. 1:在Sybase中,PreparedStatement是基于Session存储的,一个被编译好的dynSQL语句只对一个session有效,对于那些在一个Session中多次使用的dynSQL语句,使用PreparedStatement会带来性能的提升,sql越复杂使用频率越高,性能提升越大。但是如果一个dynSQL语句在一个Session下被调用的次数少,那么PreparedStatement有可能会导致性能的下降,因为编译,存储,销毁dynSQL语句也是花时间的。 2:在一个session中被编译好的dynSQL其执行效率跟储存过程的效率相似,唯一不同的是PreparedStatement编译好的dynSQL是session有效,而存储过程是全数据库有效。 3:在我上面的测试中我是采用直接连数据库的方式,所以分3次执行使用PreparedStatement的数据库插入操作每次都会重新编译,而且在测试结束时还要负责销毁编译好的查询,这也许是PreparedStatement败下阵来的原因,采用robbin的测试方法,并且sql写的很复杂,那么PreparedStatement也许会有更好的性能 |
|
返回顶楼 | |
发表时间:2007-01-24
PreparedStatement 更重要的功能是防sql 注入. |
|
返回顶楼 | |
发表时间:2007-01-24
codeutil 写道 PreparedStatement 更重要的功能是防sql 注入. 这点我同意 |
|
返回顶楼 | |
发表时间:2007-01-24
我在google上查了很久,没有我想要的PreparedStatement vs. statement的全面比较。
大部分都是泛泛的说PreparedStatement理论上怎么怎么样。 找到一个对于MySQL JDBC的讨论: http://www.mysqltalk.org/statements-vs-preparedstatements-vt112753.html 基本上说的是,Oracle里基本上始终是PreparedStatement性能更好,而MySQL则不是。 |
|
返回顶楼 | |
发表时间:2007-01-25
噩耗:mysql原来不支持PreparedStatement特性
|
|
返回顶楼 | |
发表时间:2007-01-25
哪里有说不支持了?
http://dev.mysql.com/doc/refman/5.0/en/sqlps.html 13.7. SQL Syntax for Prepared Statements MySQL 5.0 provides support for server-side prepared statements. This support takes advantage of the efficient client/server binary protocol implemented in MySQL 4.1, provided that you use an appropriate client programming interface. Candidate interfaces include the MySQL C API client library (for C programs), MySQL Connector/J (for Java programs), and MySQL Connector/NET. |
|
返回顶楼 | |
发表时间:2007-01-25
alin_ass 写道 哪里有说不支持了?
http://dev.mysql.com/doc/refman/5.0/en/sqlps.html 13.7. SQL Syntax for Prepared Statements MySQL 5.0 provides support for server-side prepared statements. This support takes advantage of the efficient client/server binary protocol implemented in MySQL 4.1, provided that you use an appropriate client programming interface. Candidate interfaces include the MySQL C API client library (for C programs), MySQL Connector/J (for Java programs), and MySQL Connector/NET. 是的,MySQL4.1以后就支持服务端的Prepared Statement了。 我搞错了,我之前的信息来源是:mysql-connector-java-5.0.3/docs/connect-j.pdf中的: PreparedStatements are implemented by the driver, as MySQL does not have a prepared statement feature. Because of this, the driver does not implement getParameterMetaData() or getMetaData() as it would require the driver to have a complete SQL parser in the client. Starting with version 3.1.0 MySQL Connector/J, server-side prepared statements and 'binary-encoded' result sets are used when the server supports them. 之前理解错了。JDBC driver是当MySQL不支持服务端Prepared Statement时(MySQL4.1之前),在Driver里实现这个特性;而当MySQL支持时(MySQL4.1之后),使用服务端的特性。 可以参考这个:http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html 虽然MySQL5支持服务端precomiple,但它实现得还比较弱啊,相对于Statement我至今没看出性能提升,相反更弱。 |
|
返回顶楼 | |