oracle index的使用_我的记事本_百度空间

Posted on

oracle index的使用我的记事本百度空间

分享到

百度分享

2011-07-23 10:13

oracle index的使用

Oracle提供了大量索引选项。知道在给定条件下使用哪个选项对于一个应用程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,这样会使您立刻成为一位英雄。这篇文章就将简单的讨论每个索引选项。主要有以下内容:

[1]基本的索引概念

查询DBA_INDEXES视图可得到表中所有索引的列表,注意只能通过USER_INDEXES的方法来检索模式(schema)的索引。访问USER_IND_COLUMNS视图可得到一个给定表中被索引的特定列。

[2]组合索引

当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个值,否则就不能使用这个索引键进行一次范围扫描。

特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!

[3] ORACLE ROWID

通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复值或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。

[4]限制索引

限制索引是一些没有经验的开发人员经常犯的错误之一。在SQL中有很多陷阱会使一些索引无法使用。下面讨论一些常见的问题:

4.1使用不等于操作符(<>、!=)

   下面的查询即使在cust_rating列有一个索引,查询语句仍然执行一次全表扫描。

     select cust_Id,cust_name

     from   customers

     where  cust_rating <> 'aa';

    把上面的语句改成如下的查询语句,这样,在采用基于规则的

    优化器而不是基于代价的优化器(更智能)时,将会使用索引。

     select cust_Id,cust_name<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

     from   customers

     where  cust_rating < 'aa' or cust_rating > 'aa';

特别注意:通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描。

 4.2使用IS NULL或IS NOT NULL

使用IS NULL或IS NOT NULL同样会限制索引的使用。因为NULL值并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索引,关于位图索引在稍后在详细讨论)。

4.3使用函数

如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。下面的查询不会使用索引(只要它不是基于函数的索引)

      select empno,ename,deptno

      from   emp

      where  trunc(hiredate)='01-MAY-81';

     把上面的语句改成下面的语句,这样就可以通过索引进行查找。

      select empno,ename,deptno

      from   emp

      where  hiredate<(to_date('01-MAY-81')+0.9999);



 4.4比较不匹配的数据类型

    比较不匹配的数据类型也是比较难于发现的性能问题之一。

    注意下面查询的例子,account_number是一个VARCHAR2类型,

    在account_number字段上有索引。下面的语句将执行全表扫描。

     select bank_name,address,city,state,zip

     from   banks

     where  account_number = 990354;

     Oracle可以自动把where子句变成to_number(account_number)=990354,这样就限制了

     索引的使用,改成下面的查询就可以使用索引:

     select bank_name,address,city,state,zip

     from   banks

     where  account_number ='990354';

特别注意:不匹配的数据类型之间比较会让Oracle自动限制索引的使用,

   即便对这个查询执行Explain Plan也不能让您明白为什么做了一次“全表扫描”。

[5]选择性

使用USER_INDEXES视图,该视图中显示了一个distinct_keys列。比较一下唯一键的数量和表中的行数,就可以判断索引的选择性。选择性越高,索引返回的数据就越少。

[6]群集因子(Clustering Factor)

Clustering Factor位于USER_INDEXES视图中。该列反映了数据相对于已索引的列是否显得有序。如果Clustering Factor列的值接近于索引中的树叶块(leaf block)的数目,表中的数据就越有序。如果它的值接近于表中的行数,则表中的数据就不是很有序。

[7]二元高度(Binary height)

索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B- level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中值的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类似于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。

[8]快速全局扫描

在Oracle7.3后就可以使用快速全局扫描(Fast Full Scan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。

[9]跳跃式扫描

从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。下面的程序清单显示出性能的差别:

create index skip1 on emp5(job,empno);

index created.



select count(/*)

from emp5

where empno=7900;



Elapsed:00:00:03.13



Execution Plan

0     SELECT STATEMENT Optimizer=CHOOSE(Cost=4 Card=1 Bytes=5)

1  0    SORT(AGGREGATE)

2  1      INDEX(FAST FULL SCAN) OF 'SKIP1'(NON-UNIQUE)



Statistics



6826 consistent gets

6819 physical   reads



select //*+ index(emp5 skip1)/*/ count(/*)

from emp5

where empno=7900;



Elapsed:00:00:00.56



Execution Plan

0     SELECT STATEMENT Optimizer=CHOOSE(Cost=6 Card=1 Bytes=5)

1  0    SORT(AGGREGATE)

2  1      INDEX(SKIP SCAN) OF 'SKIP1'(NON-UNIQUE)



Statistics



21 consistent gets

17 physical   reads

[10]索引的类型

 B-树索引

位图索引

 HASH索引

索引编排表

反转键索引

基于函数的索引

分区索引

本地和全局索引

如果一个表有大量数据被删除 需要rebuild索引,不然索引文件会变大 /#Oralce

分享到:

举报 浏览(153) 评论 转载

您可能也喜欢

评论

同时评论给

同时评论给原文作者

发布

500/0

收起|查看更多

帮助中心 | 空间客服 | 投诉中心 | 空间协议

©2012 Baidu

PreparedStatement 批量更新

Posted on

PreparedStatement 批量更新,插入数据到Oracle - 生活在爪洼岛上 - ITeye技术网站

首页 资讯 精华 论坛 问答 博客 专栏 群组 更多 ▼

招聘 搜索

您还未登录 ! 登录 注册

生活在爪洼岛上

PreparedStatement 批量更新,插入数据到Oracle **

博客分类:

批量更新,插入代码 收藏代码

  1. ///
  2. /* 更新数据库已有的customer信息
  3. /* @param List
  4. /* @return
  5. /*/
  6. public int updateExistsInfo(List updateList){
  7. //查询的SQL语句
  8. String sql = "update t_customer set LICENSE_KEY=?,CORPORATE_NAME=?,INTEGRATED_CLASSIFICATION=?,BOSSHEAD=?," +
  9. "CONTACT_PHONE=?,ORDER_FREQUENCY=?,CONTACT_ADDRESS=?,USER_ID=? where CUSTOMER_ID=?" ;
  10. //插入需要的数据库对象
  11. Connection conn = null;
  12. PreparedStatement pstmt = null;
  13. try {
  14. conn = new DBSource().getConnection();
  15. //设置事务属性
  16. conn.setAutoCommit(false);
  17. pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
  18. for(CustomerBean cbean : updateList){
  19. pstmt.setString(1, cbean.getLicense_key());
  20. pstmt.setString(2, cbean.getCorporate_name());
  21. pstmt.setString(3, cbean.getIntegrated_classification());
  22. pstmt.setString(4, cbean.getBosshead());
  23. pstmt.setString(5, cbean.getContact_phone());
  24. pstmt.setString(6, cbean.getOrder_frequency());
  25. pstmt.setString(7, cbean.getContact_address());
  26. pstmt.setInt (8, cbean.getUser_id());
  27. pstmt.setInt (9, cbean.getCustomer_id());
  28. pstmt.addBatch();
  29. }
  30. int[] tt = pstmt.executeBatch();
  31. System.out.println("update : " + tt.length);
  32. //提交,设置事务初始值
  33. conn.commit();
  34. conn.setAutoCommit(true);
  35. //插入成功,返回
  36. return tt.length;
  37. }catch(SQLException ex){
  38. try{
  39. //提交失败,执行回滚操作
  40. conn.rollback();
  41. }catch (SQLException e) {
  42. e.printStackTrace();
  43. System.err.println("updateExistsInfo回滚执行失败!!!");
  44. }
  45. ex.printStackTrace();
  46. System.err.println("updateExistsInfo执行失败");
  47. //插入失败返回标志0
  48. return 0;
  49. }finally {
  50. try{
  51. //关闭资源
  52. if(pstmt != null)pstmt.close();
  53. if(conn != null)conn.close();
  54. }catch (SQLException e) {
  55. e.printStackTrace();
  56. System.err.println("资源关闭失败!!!");
  57. }
  58. }
  59. }
  60. ///
  61. /* 插入数据中没有的customer信息
  62. /* @param List
  63. /* @return
  64. /*/
  65. public int insertNewInfo(List insertList){
  66. //查询的SQL语句
  67. String sql = "insert into t_customer(CUSTOMER_ID," +
  68. "LICENSE_KEY,CORPORATE_NAME,INTEGRATED_CLASSIFICATION,BOSSHEAD,CONTACT_PHONE," +
  69. "ORDER_FREQUENCY,CONTACT_ADDRESS,USER_ID,CUSTOMER_NUM,CUSTOMER_CODING," +
  70. "INVESTIGATION_TIME,SMS_REC_FLAG,WAP_FLAG,PRICE_GATHERING_FLAG,SOCIETY_STOCK_FLAG," +
  71. "REGION_TYPE)" +
  72. "VALUES(CUSTOMER.NEXTVAL," +
  73. "?,?,?,?,?," +
  74. "?,?,?,?,?," +
  75. "TO_DATE(?,'YYYY-MM-DD'),?,0,0,0," +
  76. "?)" ;
  77. //插入需要的数据库对象
  78. Connection conn = null;
  79. PreparedStatement pstmt = null;
  80. try {
  81. conn = new DBSource().getConnection();
  82. //设置事务属性
  83. conn.setAutoCommit(false);
  84. pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
  85. for(CustomerBean cbean : insertList){
  86. pstmt.setString(1, cbean.getLicense_key());
  87. pstmt.setString(2, cbean.getCorporate_name());
  88. pstmt.setString(3, cbean.getIntegrated_classification());
  89. pstmt.setString(4, cbean.getBosshead());
  90. pstmt.setString(5, cbean.getContact_phone());
  91. pstmt.setString(6, cbean.getOrder_frequency());
  92. pstmt.setString(7, cbean.getContact_address());
  93. pstmt.setInt(8, cbean.getUser_id());
  94. pstmt.setString(9, "gyyc00000");//
  95. pstmt.setString(10, "95000000");//
  96. pstmt.setString(11, getToday());
  97. pstmt.setInt(12, cbean.getSms_rec_flag());
  98. pstmt.setInt(13, cbean.getRegion_type());
  99. pstmt.addBatch();
  100. }
  101. int[] tt = pstmt.executeBatch();
  102. System.out.println("insert : " + tt.length);
  103. //提交,设置事务初始值
  104. conn.commit();
  105. conn.setAutoCommit(true);
  106. //插入成功,返回
  107. return tt.length;
  108. }catch(SQLException ex){
  109. try{
  110. //提交失败,执行回滚操作
  111. conn.rollback();
  112. }catch (SQLException e) {
  113. e.printStackTrace();
  114. System.err.println("insertNewInfo回滚执行失败!!!");
  115. }
  116. ex.printStackTrace();
  117. System.err.println("insertNewInfo执行失败");
  118. //插入失败返回标志0
  119. return 0;
  120. }finally {
  121. try{
  122. //关闭资源
  123. if(pstmt != null)pstmt.close();
  124. if(conn != null)conn.close();
  125. }catch (SQLException e) {
  126. e.printStackTrace();
  127. System.err.println("资源关闭失败!!!");
  128. }
  129. }
  130. }
    /// / 更新数据库已有的customer信息 / @param List / @return // public int updateExistsInfo(List updateList){ //查询的SQL语句 String sql = "update t_customer set LICENSE_KEY=?,CORPORATE_NAME=?,INTEGRATED_CLASSIFICATION=?,BOSSHEAD=?," + "CONTACT_PHONE=?,ORDER_FREQUENCY=?,CONTACT_ADDRESS=?,USER_ID=? where CUSTOMER_ID=?" ; //插入需要的数据库对象 Connection conn = null; PreparedStatement pstmt = null; try { conn = new DBSource().getConnection(); //设置事务属性 conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); for(CustomerBean cbean : updateList){ pstmt.setString(1, cbean.getLicense_key()); pstmt.setString(2, cbean.getCorporate_name()); pstmt.setString(3, cbean.getIntegrated_classification()); pstmt.setString(4, cbean.getBosshead()); pstmt.setString(5, cbean.getContact_phone()); pstmt.setString(6, cbean.getOrder_frequency()); pstmt.setString(7, cbean.getContact_address()); pstmt.setInt (8, cbean.getUser_id()); pstmt.setInt (9, cbean.getCustomer_id()); pstmt.addBatch(); } int[] tt = pstmt.executeBatch(); System.out.println("update : " + tt.length); //提交,设置事务初始值 conn.commit(); conn.setAutoCommit(true); //插入成功,返回 return tt.length; }catch(SQLException ex){ try{ //提交失败,执行回滚操作 conn.rollback(); }catch (SQLException e) { e.printStackTrace(); System.err.println("updateExistsInfo回滚执行失败!!!"); } ex.printStackTrace(); System.err.println("updateExistsInfo执行失败"); //插入失败返回标志0 return 0; }finally { try{ //关闭资源 if(pstmt != null)pstmt.close(); if(conn != null)conn.close(); }catch (SQLException e) { e.printStackTrace(); System.err.println("资源关闭失败!!!"); } } } /// / 插入数据中没有的customer信息 / @param List / @return // public int insertNewInfo(List insertList){ //查询的SQL语句 String sql = "insert into t_customer(CUSTOMER_ID," + "LICENSE_KEY,CORPORATE_NAME,INTEGRATED_CLASSIFICATION,BOSSHEAD,CONTACT_PHONE," + "ORDER_FREQUENCY,CONTACT_ADDRESS,USER_ID,CUSTOMER_NUM,CUSTOMER_CODING," + "INVESTIGATION_TIME,SMS_REC_FLAG,WAP_FLAG,PRICE_GATHERING_FLAG,SOCIETY_STOCK_FLAG," + "REGION_TYPE)" + "VALUES(CUSTOMER.NEXTVAL," + "?,?,?,?,?," + "?,?,?,?,?," + "TO_DATE(?,'YYYY-MM-DD'),?,0,0,0," + "?)" ; //插入需要的数据库对象 Connection conn = null; PreparedStatement pstmt = null; try { conn = new DBSource().getConnection(); //设置事务属性 conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); for(CustomerBean cbean : insertList){ pstmt.setString(1, cbean.getLicense_key()); pstmt.setString(2, cbean.getCorporate_name()); pstmt.setString(3, cbean.getIntegrated_classification()); pstmt.setString(4, cbean.getBosshead()); pstmt.setString(5, cbean.getContact_phone()); pstmt.setString(6, cbean.getOrder_frequency()); pstmt.setString(7, cbean.getContact_address()); pstmt.setInt(8, cbean.getUser_id()); pstmt.setString(9, "gyyc00000");// pstmt.setString(10, "95000000");// pstmt.setString(11, getToday()); pstmt.setInt(12, cbean.getSms_rec_flag()); pstmt.setInt(13, cbean.getRegion_type()); pstmt.addBatch(); } int[] tt = pstmt.executeBatch(); System.out.println("insert : " + tt.length); //提交,设置事务初始值 conn.commit(); conn.setAutoCommit(true); //插入成功,返回 return tt.length; }catch(SQLException ex){ try{ //提交失败,执行回滚操作 conn.rollback(); }catch (SQLException e) { e.printStackTrace(); System.err.println("insertNewInfo回滚执行失败!!!"); } ex.printStackTrace(); System.err.println("insertNewInfo执行失败"); //插入失败返回标志0 return 0; }finally { try{ //关闭资源 if(pstmt != null)pstmt.close(); if(conn != null)conn.close(); }catch (SQLException e) { e.printStackTrace(); System.err.println("资源关闭失败!!!"); } } }

Notice:

//设置事务属性 conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); for(CustomerBean cbean : updateList){ pstmt.setString(1, cbean.getLicense_key()); ...
pstmt.addBatch(); } int[] tt = pstmt.executeBatch(); System.out.println("update : " + tt.length); //提交,设置事务初始值 conn.commit(); conn.setAutoCommit(true); ... 分享到:

[面试技巧]如何向你的面试官“发问”(转 ... | 最后期限中的经典管理名录

评论

发表评论

您还没有登录,请您登录后再发表评论

zjx2388的博客

zjx2388

  • 浏览: 211663 次
  • 性别: Icon_minigender_2
  • 来自: 北京
  • 最近访客 更多访客>>

danrise的博客

danrise

lijianlee的博客

lijianlee yslflsy的博客

yslflsy

ws_nihao的博客

ws_nihao

文章分类

存档分类

最新评论

oracle preparedStatement ResultSet.Type_Scroll_Ins

Posted on

oracle preparedStatement ResultSet.Type_Scroll_Insensitive 乱码 - 我是一只愚 - ITeye技术网站

首页 资讯 精华 论坛 问答 博客 专栏 群组 更多 ▼

招聘 搜索

您还未登录 ! 登录 注册

我是一只愚

oracle preparedStatement ResultSet.Type_Scroll_Insensitive 乱码 **

博客分类:

问题:

我用的数据库是 oracle 字符集 us7ascii 用preparedStatement(sqlString, ResultSet.Type_Scroll_Insensitive, ResultSet.Concur_read_only) 从数据库中 读取数据后 中文字段乱码,不管是转不转码都是乱码 但是如果preparedStatement(sqlString) 转码成GBK后就能正常显示中,服了。

查询百度,有说是oracle jdbc驱动的问题,这个还没有验证,有时间验证一下,作参考。

深入理解(原文http://www.iteye.com/topic/123557

JDBC2.0后提出了三种不同的cursor类型,用户代码可以在创建Statement指定cursor类型,如下: Statement createStatement( int resultSetType, int resultSetConcurrency)

cursor类型

ResultSet.TYPE_FORWARD_ONLY

默认的cursor类型,仅仅支持向前forward,不支持backforward,random,last,first操作,类似单向链表。 TYPE_FORWARD_ONLY类型通常是效率最高最快的cursor类型

ResultSet.TYPE_SCROLL_INSENSITIVE

支持backforward,random,last,first操作,对其它数据session对选择数据做出的更改是不敏感,不可见的。

ResultSet.TYPE_SCROLL_SENSITIVE

支持backforward,random,last,first操作,对其它数据session对选择数据做出的更改是敏感,可见的。

分析

众所周知,JDBC对数据库进行数据查询时,数据库会创建查询结果的cache和cursor。而数据库的cursor是不支持 backforward,random,last,first操作,仅仅只支持向前forward。那么TYPE_SCROLL_INSENSITIVE 是如何实现支持backforward,random,last,first的呢?很简单,TYPE_SCROLL_INSENSITIVE的 Statement查询把所有fetch的记录都缓存到JVM的Resultset对象内,如果有10个记录,直接跳到最后记 录,TYPE_SCROLL_INSENSITIVE方式下把fetch所有记录到jvm端,并缓存下来,再进行random就是在数据库数组里面进行 的。这也是TYPE_FORWARD_ONLY类型通常是效率最高最快的cursor类型原因,如果要做一些复杂的功能,必然是要牺牲一些效率的。 那么为什么TYPE_SCROLL_INSENSITIVE对选择数据做出的更改是不敏感,不可见的呢?前面提到,JDBC对数据库进行数据查询时,数据库会创建查询结果的cache和cursor,如下面sql: select name,id from foo 用jdbc执行上面的sql语句时,数据库会把foo表所有记录的name和id字段缓存到cache中,之后cache和真正的数据库数据文件没有任何 联系了,foo表发生的改变在查询完成后不会自动同步到cache上去,因此TYPE_SCROLL_INSENSITIVE对选择数据做出的更改是不敏 感,不可见。 那么TYPE_SCROLL_SENSITIVE是怎么做到其它数据session对选择数据做出的更改是敏感,可见的。上面的sql语句用TYPE_SCROLL_SENSITIVE的Statement来执行,会转化成以下的sql语句: select rowid from foo 数据库这时候是把foo表所有记录的rowid缓存到cache中,用户代码在fetch记录时,再继续做以下查询: select name,id from foo where rowid=? 因此这时候发生的查询是实时从真正的数据库数据文件中取,因此对期间发生的数据更改是可见的,敏感的。但是这种可见性仅限于update操作,而 insert和delete同样是不可见的。因为如果查询发生在insert之前,insert生成的rowid并不会反应在cache中的rowid结 果集上。在一个记录的rowid已经缓存到cache中,这时候被删除了,但一般数据库的删除是标记删除,也就是说rowid对应那行记录并没有真正从数 据库文件中抹去,一般是可以再次取到记录的。

总结

TYPE_FORWARD_ONLY类型通常是效率最高最快的cursor类型,也是最常用的选择。
TYPE_SCROLL_INSENSITIVE需要在jvm中cache所有fetch到的记录实体,在大量记录集返回时慎用。
TYPE_SCROLL_SENSITIVE在jvm中cache所有fetch到的记录rowid,需要进行二次查询,效率最低,开销最大

JDBC ResultSet分析 (原文http://www.iteye.com/topic/560109

JDBC1.0 、JDBC2.0 、JDBC3.0 中分别用以下方法创建Statement 。

JDBC1.0 : createStatement()

JDBC2.0 : createStatement(resultSetType, resultSetConcurrency)

JDBC3.0 : createStatement(resultSetType, resultSetConcurrency, resultSetHoldability)

下面依次分析resultSetType 、resultSetConcurrency 、resultSetHoldability 这几个参数的含义。

一 ResultSetType

  resultSetType 的可选值有: ResultSet.TYPE_FORWARD_ONLY 、ResultSet.TYPE_SCROLL_INSENSITIVE 、ResultSet.TYPE_SCROLL_SENSITIVE 。

1 :ResultSet.TYPE_FORWARD_ONLY

默认的cursor 类型,仅仅支持结果集forward ,不支持backforward ,random ,last ,first 等操作。

2 :ResultSet.TYPE_SCROLL_INSENSITIVE

支持结果集backforward ,random ,last ,first 等操作,对其它session 对数据库中数据做出的更改是不敏感的。

实现方法:从数据库取出数据后,会把全部数据缓存到cache 中,对结果集的后续操作,是操作的cache 中的数据,数据库中记录发生变化后,不影响cache 中的数据,所以ResultSet 对结果集中的数据是INSENSITIVE 的。

3 :ResultSet.TYPE_SCROLL_SENSITIVE

支持结果集backforward ,random ,last ,first 等操作,对其它session 对数据库中数据做出的更改是敏感的,即其他session 修改了数据库中的数据,会反应到本结果集中。

实现方法:从数据库取出数据后,不是把全部数据缓存到cache 中,而是把每条数据的rowid 缓存到cache 中,对结果集后续操作时,是根据rowid 再去数据库中取数据。所以数据库中记录发生变化后,通过ResultSet 取出的记录是最新的,即ResultSet 是SENSITIVE 的。 但insert 和delete 操作不会影响到ResultSet ,因为insert 数据的rowid 不在ResultSet 取出的rowid 中,所以insert 的数据对ResultSet 是不可见的,而delete 数据的rowid 依旧在ResultSet 中,所以ResultSet 仍可以取出被删除的记录( 因为一般数据库的删除是标记删除,不是真正在数据库文件中删除 )。

做个试验,验证一下SENSITIVE 特性。数据库为oracle10g ,驱动为ojdbc14.jar 。

test 表中数据如下:

c1 c2 c3 1c1 1c2 1c3 2c1 2c2 2c3 3c1 3c2 3c3

程序如下: Java代码 收藏代码

  1. public static void testResultSetSensitive(Connection conn) throws Exception{
  2. String sql = "SELECT c1,c2,c3 FROM test" ;
  3. try {
  4. Statement stmt = conn
  5. .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
  6. ResultSet rs = stmt.executeQuery(sql);
  7. while (rs.next()) {
  8. System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString( 1 ) + "\t" + rs.getString( 2 )
    • "\t" + rs.getString( 3 ));
  9. Thread.sleep(20000 );
  10. }
  11. rs.close();
  12. stmt.close();
  13. } catch (SQLException e) {
  14. e.printStackTrace();
  15. } finally {
  16. try {
  17. conn.close();
  18. } catch (Exception e) {
  19. }
  20. }
  21. }

定义ResultSet 为 ResultSet. TYPE_SCROLL_SENSITIVE 类型,首先执行 sql 访问数据库,然后执行 rs.next() 移动游标取数据。在循环里面加上 Thread.sleep (20000) 的目的是为了我们有时间在后台把数据库里的数据改了。比如当在循环里打印出第一行的数据后,我们在后台,把第三行数据的 c3 列改成 ”3uuu” 。如果 ResultSet 真的是敏感的话,那应该取出 ”3uuu” ,而不是原始的“ 3c 3 ”。但最终的结果却是如下:

[ 行号: 1] 1c1 1c2 1c3

[ 行号: 2] 2c1 2c2 2c3

[ 行号: 3] 3c1 3c2 3c3

数据没变呀,ResultSet 不敏感啊!于是去查阅资料,找了n 久,还是在英文文档上找到了答案。原来是fetchsize 的问题。调用ResultSet 的next 方法取数据时,并不是每调用一次方法就去数据库里查一次,而是有个fetchSize, 一次取fetchSize 条数据。Oracle 默认的fetchsize 等于10 ,所以上面的代码在第一次调用rs.next() 时,就已经把3 条数据都取出来了,所以才会有上面的结果。

  第二次实验,在ResultSet rs = stmt.executeQuery(sql); 前面加上 stmt.setFetchSize(1); 将fetchSize 设置为1 。然后重新第一次实验的步骤,发现最 终结果为:

[ 行号: 1] 1c1 1c2 1c3

[ 行号: 2] 2c1 2c2 2c3

[ 行号: 3] 3c1 3c2 3uuu

原因就是 fetchsize 设置为 1 时,每次 next 取数时都会重新用 rowid 取数据库里取数据,当然取到的是最新的数据了。



 **二 ResultSetConcurrency**



  ResultSetConcurrency的可选值有2个:
  ResultSet.CONCUR_READ_ONLY 在ResultSet中的数据记录是只读的,不可以修改
  ResultSet.CONCUR_UPDATABLE 在ResultSet中的数据记录可以任意修改,然后更新到数据库,可以插入,删除,修改。



 **三 ResultSetHoldability**

ResultSetHoldability 的可选值有2 个 :

 HOLD_CURSORS_OVER_COMMIT:  在事务commit 或rollback 后,ResultSet 仍然可用。
 CLOSE_CURSORS_AT_COMMIT:  在事务commit 或rollback 后,ResultSet  被关闭。



 需要注意的地方:

1 :Oracle 只支持HOLD_CURSORS_OVER_COMMIT 。

2 :当Statement 执行下一个查询,生成第二个ResultSet 时,第一个ResultSet 会被关闭,这和是否支持支持HOLD_CURSORS_OVER_COMMIT 无关。

四 验证数据库是否支持ResultSet的各种特性

不同的数据库版本及 JDBC 驱动版本,对 ResultSet 的各种高级特性的支持是不一样的,我们可以通过以下方法,来验证具体的数据库及 JDBC 驱动,是否支持 ResultSet 的各种特性。

 DatabaseMetaData dbMeta = conn.getMetaData();

   然后调用 DatabaseMetaData 对象的以下方法:

   boolean supportsResultSetType(int resultSetType);

   boolean supportsResultSetConcurrency(int type, int concurrency);

    boolean supportsResultSetHoldability(int holdability);



  参考的2 篇英文文档:

http://cs.felk.cvut.cz/10gr2/java.102/b14355/jdbcvers.htm (JDBC Standards Support )

http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/resltset.htm/#1023642 (Oracle9i JDBC Developer's Guide and Reference Release 2 (9.2)) 分享到:

JAVA5的新特性收集 | ORACLE:按月累计问题的解决方法

评论

发表评论

您还没有登录,请您登录后再发表评论

vvnet的博客

vvnet

  • 浏览: 28526 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
  • 最近访客 更多访客>>

coldsummerwei的博客

coldsummerwei

shadow19831112的博客

shadow19831112 hwf52591的博客

hwf52591

17369644的博客

17369644

文章分类

存档分类

oracle 查询占用消耗 CPU 的进程sql

Posted on

oracle 查询占用消耗 CPU 的进程sql

枫的个人空间

copy Bookmark http://space.itpub.net/24015283

空间管理 您的位置: ITPUB个人空间 枫的个人空间 日志

一叶知秋!

oracle 查询占用消耗CPU的进程sql

上一篇 / 下一篇 2011-10-14 14:47:47 查看( 220 ) / 评论( 0 ) / 评分( 0 / 0 )

  1. top查看占用CPU比较高的进程ID,并记录下来

例如:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31189 nxuser 15 0 12436 11m 256 S 55.4 0.1 35626:21 oracle
32902 oracle 16 0 1304m 1.0g 1.0g S 1 12.5 13:07.28 oracle
5784 nxuser 16 0 2368 1104 780 S 0 0.0 0:00.02 oracle
28779 nxuser 16 0 2364 1140 780 R 0 0.0 0:25.28 top

Pid 31189占用CPU显然是比较高的

Sqlpusl连接登陆ORACLE

2.执行下面的语句,查得相对应的系统进程对应的session id

SQL> select sid from v$session where paddr in (select addr from v$process where spid=&spid);

Enter value for spid: 31189

old 1: select sid from v$session where paddr in (select addr from v$process where spid=&spid)

new 1: select sid from v$session where paddr in (select addr from v$process where spid=31189)

  SID

   206

3.根据所得的会话ID查得sql地址和hash值

SQL> select sql_address,sql_hash_value from v$session where sid=206;

SQL_ADDR SQL_HASH_VALUE


6EC554F4 3141392848

4.根据sql hash值查得sql语句

SQL> select sql_text from v$sqltext where hash_value=3141392848;

SQL_TEXT


INSERT INTO TEST SELECT /* FROM SYS.DBA_OBJECTS

5.若没查得相应的sql地址和hash值,请查询job

导入论坛 引用链接 收藏 分享给好友 推荐到圈子 管理 举报

TAG: 查看全部评论

-5 -3 -1 - +1 +3 +5

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

内容

昵称

验证 seccode

提交评论

yefeng139

yefeng139

用户菜单

日历

2012-11-07 日 一 二 三 四 五 六 123456789101112131415161718192021222324252627282930

我的存档

数据统计

  • 访问量: 521
  • 日志数: 8
  • 建立时间: 2011-09-05
  • 更新时间: 2012-06-15

    RSS订阅

  • RSS订阅

清空Cookie - 联系我们 - ITPUB个人空间 - 交流论坛 - 空间列表 - 站点存档 - 升级自己的空间

Powered by X-Space 3.0.2 2001-2007 Comsenz Inc. 京ICP证:010037号网站统计 我要啦免费统计 Open Toolbar