jdbc优化[手工原创] - 泉水 - JavaEye技术网站
luyued 发布于 2011-01-14 18:42 浏览 N 次为了区分出这三者之间的效率,下面的事例执行过程都是在数据库表t1中插入1万条记录,并记录出所需的时间(此时间与电脑硬件有关)
缺点 : 采用硬编码
public void exec(Connection conn){
Long beginTime = System.currentTimeMillis();
conn.setAutoCommit(false);// 设置手动提交
Statement st = conn.createStatement();
for(int i=0;i<10000;i++){
String sql="insert into t1(id) values ("+i+")";
st.executeUpdate(sql);
Long endTime = System.currentTimeMillis();
System.out.println("Statement 用时 : "+(endTime-beginTime)/1000+" 秒 ");// 计算时间
st.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
执行时间: Statement 用时: 31 秒
2. 预编译 PreparedStatement
使用范围:当执行相似 sql 语句的次数比较多(例如用户登陆,对表频繁操作 .. )语句一样,只是具体的值不一样,被称为动态SQL
优点:语句只编译一次,减少编译次数。提高了安全性(阻止了SQL注入)
缺点 : SQL 语句 时,速度较慢。
SQL注入:select * from user where username="张三" and password="123" or 1=1 ;
public void exec2(Connection conn){
Long beginTime = System.currentTimeMillis();
conn.setAutoCommit(false);// 手动提交
PreparedStatement pst = conn.prepareStatement("insert into t1(id) values (?)");
for(int i=0;i<10000;i++){
pst.setInt(1, i);
pst.execute();
Long endTime = System.currentTimeMillis();
System.out.println("Pst 用时 :"+(endTime-beginTime)+" 秒 ");// 计算时间
pst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
执行时间 : Pst 用时 :14 秒
3. 使用 PreparedStatement + 批处理
优点:减少和SQL引擎交互的次数,再次提高效率,相似语句只编译一次,减少编译次数。提高了安全性(阻止了 SQL 注入)
PL/SQL引擎:在oracle中执行pl/sql代码的引擎,在执行中发现标准的sql会交给sql引擎进行处理。
public void exec3(Connection conn){
conn.setAutoCommit(false);
Long beginTime = System.currentTimeMillis();
PreparedStatement pst = conn.prepareStatement("insert into t1(id) values (?)");
for(int i=1;i<=10000;i++){
pst.setInt(1, i);
加入批处理 , 进行打包
if(i%1000==0){// 可以设置不同的大小 ; 如 50 , 100 , 500 , 1000 等等
pst.executeBatch();
Long endTime = System.currentTimeMillis();
System.out.println("pst+batch 用时 : "+(endTime-beginTime)+" 毫秒 ");
pst.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
执行时间 : pst+batch 用时 : 485 毫秒
原理: ( 检查 SQL 语句在 SGA 中的共享池中是否存在 , 如果不存在,则编译、解析后执行:硬解析 ,
如果已存在,则取出编译结果执行:软解析 )
DECLARE
time1 NUMBER;
time2 NUMBER;
BEGIN
time1 := dbms_utility.get_time;
EXECUTE IMMEDIATE 'truncate table t_demo';
FOR i IN 1..10000
LOOP
EXECUTE IMMEDIATE
'insert into t_demo(u_id) values('||i||')';
END LOOP;
time2 := dbms_utility.get_time;
dbms_output.put_line((time2-time1)/100||' 秒
执行时间: pst+batch 用时: 20.93 秒
原理: 减少编译次数 ( 检查 SQL 语句在 SGA 中的共享池中是否存在 , 如果不存在,则编译、解析后执行:硬解析 ,
如果已存在,则取出编译结果执行:软解析 )
DECLARE
time1 NUMBER;
time2 NUMBER;
BEGIN
time1 := dbms_utility.get_time;
EXECUTE IMMEDIATE 'truncate table t_demo';
FOR i IN 1..10000
LOOP
EXECUTE IMMEDIATE
'insert into t1(u_id) values(:x)' USING i;
END LOOP;
time2 := dbms_utility.get_time;
dbms_output.put_line((time2-time1)/100||' 秒
执行时间: pst+batch 用时: 10.55 秒
3 利用 forall 进行批处理<相似java中的批处理>
使用范围:当执行相似 sql 语句的次数比较多(例如用户登陆,对表频繁操作 ..
缺点 : 循环时从开始到结束,一次性读完,不能取其中的某些循环进行操作。
原理: 使用 ForAll 语句可以让 PL/SQL 引擎一次将多条 SQL 转发给 SQL 引擎,从而减少转发次数,提高系统性能。
CREATE OR REPLACE PROCEDURE p_test
AS
-- 定义新的类型 ( 不是定义变量! )
TYPE id_table_type IS TABLE OF NUMBER(6) INDEX BY BINARY_INTEGER;
-- 用新的类型来定义变量
id_table id_table_type;
time1 NUMBER;
time2 NUMBER;
BEGIN
FOR i IN 1..10000
LOOP
-- 往两个数组中存放数据
id_table(i) := i;
END LOOP;
-- ★ :一次性向 SQL 引擎传递了多条数据而不是一条
time1 := dbms_utility.get_time;
FORALL i IN 1..id_table.COUNT
INSERT INTO t_demo(u_id) VALUES(id_table(i));
time2 := dbms_utility.get_time;
dbms_output.put_line((time2-time1)*10||' 毫秒
执行时间: pst+batch 用时: 170 毫秒
IS TABLE OF book%ROWTYPE
BULK COLLECT INTO book
WHERE title LIKE '%PL/SQL%';
发表评论您还没有登录,请登录后发表评论(快捷键 Alt+S / Ctrl+Enter)
引文来源 jdbc优化[手工原创] - 泉水 - JavaEye技术网站
- 07-01· 禁教唐诗算术能还幼儿快
- 07-01· 2011年06月17日
- 07-01· 唐诗宋词英译:李商隐 筹
- 07-01· 仿评《唐诗1000首》第186首
- 07-01· 没事干的时候背背唐诗吧
- 07-01· [转载]唐诗中“斜”字该读
- 07-01· 湖南醴陵瓷业转型升级
- 07-01· 奇瑞风云2两厢黑色|2010款
- 07-01· 摩根士丹利华鑫摩根士丹
- 07-01· 摩根士丹利华鑫近期优选
- 07-01· 中金投行部大摩出售中金
- 07-01· 摩根士丹利招聘6月2日【实
- 07-01· 营养防病圣典
- 07-01· 《博伽梵歌原意》之第十
- 07-01· [不错]斑斓圣典---减肥中常
- 07-01· 武乐圣典《太极武当》:武
- 07-01· 铁血英雄-现阶段战功牌兑
- 07-01· 2011年06月10日【原创】南歌
- 07-01· 【淘宝网信息】- 2010年的
- 07-01· 深圳品牌女装有哪些?