使用Oracle SQL测试

实验环境

机器:win10虚机

配置:4c8G + 500G硬盘

持续写入

每次insert操作后,进行一次commit操作,性能低。实验用时:00:02:39.66

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
drop table t purge;
create table t(x int);

-- 清空共享池,注意在生产环境中千万不能做这步操作
alter system flush shared_pool;

-- 定义函数proc
create or replace procedure proc
as
begin
for i in 1 .. 1000000
loop
insert into t values(i);
commit;
end loop;
end;
/

-- 开启sql时间统计
set timing on;

-- 运行函数proc
exec proc;

持续写入

批量写入

对insert操作进行批量提交,性能相较于上者有所提升。实验用时:00:01:25.37

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
drop table t purge;
create table t(x int);

-- 清空共享池,注意在生产环境中千万不能做这步操作
alter system flush shared_pool;

-- 定义函数proc
create or replace procedure proc
as
begin
for i in 1 .. 1000000
loop
insert into t values(i);
end loop;
commit;
end;
/

-- 开启sql时间统计
set timing on;

-- 运行函数proc
exec proc;

批量写入

connect by方式写入

Oracle提供的层次查询(Hierarchical Queries)功能中的connect by子句可以快速插入连续数字。该方法会将数据写入数据缓冲区(data buffer)中,然后刷入磁盘中。实验用时:00:00:01.56

1
2
3
4
5
6
7
8
9
10
11
drop table t purge;
create table t(x int);

-- 清空共享池,注意在生产环境中千万不能做这步操作
alter system flush shared_pool;

-- 开启sql时间统计
set timing on;

-- 使用connect by level,插入连续数字
insert into t select rownum from dual connect by level<=1000000;

connect by写入

直接路径写入

该方式跳过了数据缓冲区(data buffer), 直接写进磁盘中,这种方式称之为直接路径读写方式。实验用时:00:00:00.78

1
2
3
4
5
6
7
8
9
10
drop table t purge;

-- 清空共享池,注意在生产环境中千万不能做这步操作
alter system flush shared_pool;

-- 开启sql时间统计
set timing on;

-- 使用connect by level,插入连续数字
create table t as select rownum x from dual connect by level<=1000000;

直接路径写入

并行模式直接写入

并行加直接路径,而且是不写日志。实验用时:00:00:00.67

1
2
3
4
5
6
7
8
9
10
drop table t purge;

-- 清空共享池,注意在生产环境中千万不能做这步操作
alter system flush shared_pool;

-- 开启sql时间统计
set timing on;

-- 使用connect by level,插入连续数字
create table t nologging parallel 4 as select rownum x from dual connect by level<=1000000;

并行模式写入

大对象存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
-- 创建测试表
create table t
(
tid int primary key,
tname varchar2(20),
tcontent blob
);

-- 创建普通序列号
create sequence sequ_t;

-- 注册目录
create or replace directory TEST_DIR as 'C:\Users\lenovo\Desktop';

-- 存储文件对象
declare
tempimg blob; -- 定义临时变量存放数据
tempdir bfile := bfilename('TEST_DIR','test.png'); -- 非常重要:DIR必须大写
begin
insert into t values (sequ_t.nextval,'test.png',empty_blob())
returning tcontent into tempimg;

-- 使用内置的包,给tempimg写入数据
dbms_lob.fileopen(tempdir); -- 打开指定文件
dbms_lob.loadfromfile(tempimg,tempdir,dbms_lob.getlength(tempdir));
dbms_lob.fileclose(tempdir); -- 关闭文件
commit;
end ;
/

-- 读取文件对象
declare
l_file utl_file.file_type; -- 定义写入磁盘文件的类型和格式
l_buffer raw(32767); -- 定义缓冲区大小
l_amount binary_integer := 3276; -- 每次位移个数
l_pos int :=1; -- 开始位置
l_blob blob; -- 临时数据存放
l_blob_len int; -- 总长度
begin
-- 将数据库中的数据,存放在blob变量中
select tcontent into l_blob from t where tname='test.png';

-- 获取blob文件的长度
l_blob_len := dbms_lob.getlength(l_blob);

-- 准备写入磁盘文件
l_file := utl_file.fopen('TEST_DIR','t.png','wb');

-- 写入数据
while l_pos<l_blob_len
loop
dbms_lob.read(l_blob,l_amount,l_pos,l_buffer);
utl_file.put_raw(l_file,l_buffer,true);
l_pos := l_pos + l_amount;
end loop;
utl_file.fclose(l_file);
end;
/

存储image

读取image

参考文档