示例
--创建测试表
SQL> create table test(id int, info clob);
操作已执行
--插入2万条,clob字段长度为2000的数据,并提交
SQL> insert into test select level,rpad('1',2000,'abcd') from dual connect by level< =20000;
影响行数 20000
SQL> commit;
操作已执行
--查clob字段数据长度
SQL> select lengthb(info) from test limit 1;
行号 lengthb(info)
---------- -------------
1 2000
批量获取clob数据java程序代码:
package jdbc_conn;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class test {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("dm.jdbc.driver.DmDriver");
connection = DriverManager.getConnection("jdbc:dm://IP:端口", "用户名", "密码");
String sql = "select * from test where rownum <=10000";
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
List<String> data = new ArrayList<>();
Long stime = System.currentTimeMillis();
while(resultSet.next()){
data.add(resultSet.getString("info"));
}
System.out.println("耗时:"+(System.currentTimeMillis()-stime)+" ms");
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行java程序获取1万条数据,耗时约10秒
为什么这么慢?
原因:lob数据根据长度分行内数据和行外数据,行内数据和行外数据在读取逻辑上有差异,会采用不同方式读取,在性能上有较大差别。
解决方法:
dm.ini中有个参数可以更改行内外数据界定。
LOB_MAX_INROW_LEN 动态参数,系统级
指定数据库 LOB 字段的行内数据存放的上限大小,单位为 BYTE,有效值范围(900~8000)。
我们查询一下当前 LOB_MAX_INROW_LEN 的值:
SQL> select para_name,para_value from v$dm_ini where para_name = 'LOB_MAX_INROW_LEN';
行号 para_name para_value
---------- ----------------- ----------
1 LOB_MAX_INROW_LEN 900
当前为默认值900,但clob数据长度为2000,所以读取方式为行外数据方式读取。
我们将 LOB_MAX_INROW_LEN 参数设置为3000
SQL> sp_set_para_value(1,'LOB_MAX_INROW_LEN',3000);
DMSQL 过程已成功完成
SQL> select para_name,para_value from v$dm_ini where para_name = 'LOB_MAX_INROW_LEN';
行号 para_name para_value
---------- ----------------- ----------
1 LOB_MAX_INROW_LEN 3000
再次执行java程序,看看有什么变化。
执行时间为252毫秒,性能有大幅提升,但要注意的是,由于每行数据长度不能超过页大小的一半,所以这个参数设置时需考虑数据库的页大小,否则不起作用。