设为首页收藏本站优领域

优领域

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
优领域 优领域 IT领域 数据库 Oracle 查看内容

Oracle 数据库大对象数据存取的两种实现方法及时间性能比较

2014-5-21 10:06| 发布者: dzly| 查看: 700| 评论: 0|原作者: 袁勇

摘要: 随着云计算、物联网时代的到来,大对象数据的存储和读取将是不得不面对的现实,系 统化的数据管理才能使我们的工作事半功倍. 本文讨论利用SQL* Plus 存储过程或借助JAVA 编程语言,来实现了Oracle 数据库中大对象数据存取,并对其操作的时间性能进行对比,得出借 助JAVA 语言读取Oracle 数据库大对象远优于通过存储过程读取的结论.

  0 引言
  当代,大数据无处不在,和云计算、物联网一样已经成为计算机学科中的一个热门研究课题. 随着高清图像、视频的问世,大容量的存储空间和大数据的操作越来越需要研究者去攻克. 本文只是针对大对象数据在Oracle 数据库中的存取着手,利用  SQL* Plus 或借助JAVA 编程语言,来实现了Oracle数据库中大对象数据存取操作,并对两种方法进行存取时间性能比较,为大对象在Oracle 数据库中的存取提出一些自己的见解.
  1 Oracle 中大对象数据分类
  为了解决数据库中非结构化数据存取问题,Oracle 提出了LOB( Large Object) ,即大对象的概念,包含图像、音视频、文件等非结构化的数据. 这类数据最大特点是: 大小不确定,长度变化,要想在数据库中进行存取,就必须使用到LOB[1].
  1. 1 按数据类型分类[23]
  ①字符类型: 包含CLOB 和NLOB;
  ②二进制类型: BLOB,用来存储较大,且无结构的二进制数据;
  ③二进制文件类型: BFILE,将数据在外部操作系统文件中进行存储;
  1. 2 按存取方式分类
  ①数据在内部表空间存储: CLOB、NLOB 以及
  BLOB;
  ②指向操作系统的目录: BFILE,建立目录、文
  件的映射关系
  2 Oracle 中大对象数据存取的实现方法
  本章通过Oracle 自带的SQL* Plus 以及用当前广泛使用的JAVA 语言来实现Oracle 数据库中图片数据的存取. 首先在Oracle10g 数据库中新建测试用表[4].
  create table pic_lob
  ( t_id varchar2( 30) not null,
  t_pic blob not null) ;
  创建文件操作目录,用于大对象数据的存取.create or replace directory Pic as 'D: \test'; / /设置目录  设置好操作目录后,需要将目录的读、写权限赋予我们登陆数据库的用户.
  Grant write( read) on directory Pic to scott;
  2. 1 利用PL /SQL 实现存取
  以下为两个PL /SQL 存储过程,分别用来向数据库中存储、读取大对象数据. 可以根据修改具体的filename 名,像数据库中插入图片、视频等数据.具体如下:
  2. 1. 1 存入大对象的存储过程:
  create or replace procedure pic_insert (
  tid varchar2,
  filename varchar2 ) as
  bf bfile;
  b_lob blob;
  begin
  insert into pic_lob values ( tid ,empty_blob( ) ) return T_pic into
  b_lob; / /插入数据,空大对象
  bf : = bfilename( ' PIC', filename ) ; / /filname 为插入大对象的
  文件名
  dbms_lob. fileopen( bf,dbms_lob. file_readonly ) ;
  dbms_lob. loadfromfile( b_lob,bf,dbms_lob. getlength( bf) ) ;
  dbms_lob. fileclose( bf) ;
  commit;
  end;
  2. 1. 2 读取的存储过程:
  create or replace procedure pic_read (
  pinm varchar2 ,ponm varchar2) is
  l_file UTL_FILE. FILE_TYPE;
  l_buffer RAW( 32767) ;
  l_amount BINARY_INTEGER: = 1;
  l_pos INTEGER: = 1;
  l_blob BLOB;
  l_blob_len INTEGER;
  BEGIN
  SELECT T_PIC
  INTO l_blob
  FROM pic_lob
  WHERE T_ID = pinm;
  l_blob_len: = DBMS_LOB. GETLENGTH( l_blob) ; / /获取大对
  象长度
  l_file: = UTL_FILE. FOPEN( ' PIC',ponm, 'wb',32767) ;
  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) ; / /关闭文件读写
  EXCEPTION / /异常处理
  WHEN OTHERS THEN
  IF UTL_FILE. IS_OPEN( l_file) THEN
  UTL_FILE. FCLOSE( l_file) ;
  END IF;
  RAISE;
  END;
  /
  在完成存储过程的创建后,通过执行exec pic_  insert 或exec pic_read 存储过程,并加上相应的实  际参数完成大对象的读取.  

  2. 2 借助JAVA 编程语言实现高效读取由于使用PL /SQL 存储过程读取的效率太低( 见第三章) ,通常的系统开发都会选择使用高级程序语言,其具有界面友好、可读性强等优势,而JAVA 语言由于其跨平台等众多优点,在当前具有较大的应用市场,也是众多编程爱好者首选的开发语言. 在这里,通过JDBC 来访问oracle 数据库,实现其存取. 主要实现代码如下:
  2. 2. 1 存入大对象的JAVA 函数片段:
  public static void main( String[] args) {
  try {
  String URL = " jdbc: oracle: thin: @ localhost: 1521: ZYNC" ;
  Class. forName( " oracle. jdbc. driver. OracleDriver" ) ; / /驱动的
  加载
  Connection cnt = DriverManager. getConnection(
  URL,"
  scott","
  tiger" ) ; / / 获取数据库连接
  cnt. setAutoCommit( false) ; / /关闭自动提交
  Statement smt = cnt. createStatement( ) ;
  OutputStream os = null;
  smt. executeUpdate( " insert into pic_lob( t_id,t _pic) values ( '
  012', empty_blob( ) ) " ) ; / /插入空大对象
  ResultSet rst = smt. executeQuery ( " select t _ pic from pic _ lob
  where t_id = '012' for update" ) ; / /对空对象进行更新
  if( rst. next( ) )
  {
  oracle. sql. BLOB blob = ( oracle. sql. BLOB) rst. getBlob ( " t _
  pic" ) ;
  os = blob. getBinaryOutputStream( ) ;
  InputStream is = new FileInputStream ( " D: \ test \ Mountain.
  jpg" ) ;
  / /指定输入数据流
  int i = 0;
  while ( ( i = is. read( ) ) ! = - 1)
  { os. write( i) ; }
  }
  os. flush( ) ;
  os. close( ) ; / /关闭数据流
  cnt. commit( ) ; / /执行提交
  cnt. setAutoCommit( true) ;
  } catch ( Exception e) {
  e. printStackTrace( ) ;
  } }
  2. 2. 2 读取大对象的JAVA 函数片段:
  public static void main( String[] args)
  {
  try {
  String URL = " jdbc: oracle: thin: @ localhost: 1521: ZYNC" ;
  Class. forName( " oracle. jdbc. driver. OracleDriver" ) ; / /驱动的
  加载
  Connection cnt = DriverManager. getConnection(
  URL,"
  scott","
  tiger" ) ; / /获取数据库连接
  Statement smt = cnt. createStatement( ) ;
  ResultSet rst = smt. executeQuery ( " select t _ pic from pic _ lob
  where t_id = '012' " ) ; / /执行查询
  if( rst. next( ) )
  {
  oracle. sql. BLOB blob = ( oracle. sql. BLOB) rst. getBlob( 1) ;
  InputStream is = blob. getBinaryStream( ) ;
  FileOutputStream fos = new FileOutputStream( " E: \ outputimage.
  jpg" ) ;
  / /指定文件输出位置
  int i = 0;
  while ( ( i = is. read( ) ) ! = - 1)
  { fos. write( i) ; }
  fos. flush( ) ;
  fos. close( ) ; / /关闭数据流
  }
  } catch ( Exception e) {
  e. printStackTrace( ) ;
  } }
  3 存取时间性能比较
  在性能分析过程中,以图片( 30. 8KB \  4546KB, JPG 格式) 、视频( 422MB,MP4 格式) 的存取为例,在执行SQL* Plus 存储过程时,加入以下的命令获取存储过程执行时的系统时间,比较执行前后的执行时间差值,从而得出存储过程的运行时长.select to_char( current_timestamp( 5) ,'DD -  MON - YYYY HH24: MI: SSxFF' ) from dual;在java 连接oracle 数据库读取大对象的函数中加入函数currentTimeMillis( ) 来获取执行的系统时间,通过执行前后系统时间差来得出读取的时长.  long sysDate = System. currentTimeMillis( ) ; / /放在程序头
  long sysDate1 = System. currentTimeMillis( ) ; / /放在程序尾
  long sysDate2 = sysDate1 - sysDate;
  System. out. println( " 运行时间: " + sysDate2 + " ms" ) ; / /打印
  程序时长.
  在存储过程、JAVA 混合编程下分别运行三次,取平均数据得到耗时表如下( 打斜线表格栏:表示执行速度太长或太短,对结论不影响,而未做该项试验. ) :


  由上表可知,在进行大对象的存取过程中,通过混合编程写入数据流的方式在读取方面远优于存储过程,而在存入时性能低于存储过程.
  4 总结
  本文通过BLOB 大对象在oracle 数据库中的存取为背景,通过使用存储过程的方式和用JAVA与Oracle 混合编程的实现方式,作出系列实验研究. 得出用JAVA 与Oracle 混合编程的方式在读取大对象的过程中,远优于通过存储过程实现的结论.
  参考文献:
  [1] 金杰. 基于OCCI 技术存取数据库大对象的方法及实现[J]  . 计算机系统应用,2010, 19( 7) : 162 - 165.
  [2] 余秋明. 浅论大型数据对象在Oracle 数据库中的存储方法  [J]. 科技广场,2008,1
  0: 61 - 63.
  [3] 张文东,刘培刚. 基于Java 与Oracle 数据库的图像处理技术  [J]. 计算机系统应用, 2004, 11: 34 - 36.
  [4] 王彬,代彦波,颜鹏博. Oracle10g 简明教程[M]. 北京: 清华  大学出版社, 2006.
  

网站统计|优领域|优领域 ( 粤ICP备12011853号-1 )  

GMT+8, 2019-1-20 15:13 , Processed in 0.060085 second(s), 12 queries .

Copyright © 2008-2014 优领域

回顶部