你好,游客 登录 注册 搜索
背景:
阅读新闻

如何使用JDBC快速处理大数据

[日期:2013-07-31] 来源:CSDN  作者: [字体: ]

在实习工作中,要处理一张存有204万记录的表,由于记录是从互联网上取到的,所以里面有一些不太理想的词,比如一些词里混有特殊字符,标点符号,或者有些词根本就是标点符号等等。我写这个程序的目的就是把这些不理想的词找出来,能修改的就修改,没有必要修改的就直接删除。

[java] view plaincopy
 
  1. for(int i=0;i<205;i++) 
  2.             { 
  3.                 String sql="select * from cat_keyword order by id limit "+i*10001+",10000";           
  4.                 String best="select * from cat_keyword where id>=(select id from cat_keyword order by id limit "+i*10001+",1)limit 10000"
  5.                 rs=stmt.executeQuery(best); 
  6.                 go.filt(rs); 
  7.             } 

经试验,第一条sql语句的执行效率是明显不如第二条的。

String best="select * from cat_keyword where id>=(select id from cat_keyword order by id limit "+i*10001+",1)limit 10000";

这条SQL语句尤其适用于offset特别大的情景,因为200多万条记录,到中后期,这个offset是很大的,使用未经优化的SQL语句,到后期是越来越慢。

另外limit的取值也很有考究,我试过1000,10000,70000,100000的,最后发现limit取10000的时候速度是最快的,这个跟数据的大小,电脑以及数据库内存的分配都有一定的关系,大家可以根据具体情况具体讨论。我这里仅仅提一下需要注意,可以优化的point。

我真正想说的是我想的另外一种解决方案,运用JDBC

下面给大家说下我这个程序的构造,首先是一个实现将需要删除和修改的词插入另一张表的方法

[java] view plaincopy
 
  1. //将找到的违规词插入cat_garbage表里 
  2.    public void insert(ResultSet rs) throws SQLException 
  3.    { 
  4.        Connection conn=null
  5.         Statement stmt=null
  6.        try{           
  7.             conn=Good.getConnection(); 
  8.                 stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE 
  9.                     , ResultSet.CONCUR_UPDATABLE); 
  10.                 String query="select * from cat_garbage where id='"+rs.getInt("id")+"'"
  11.                 ResultSet rst=stmt.executeQuery(query); 
  12.                 if(!rst.next()) 
  13.                 { 
  14.                     String sql1="insert into cat_garbage(id,cid,name,keyword) values('"+rs.getInt("id")+"','"+rs.getInt("cid")+"','"+rs.getString("name")+"','"+rs.getString("keyword")+"')"
  15.                     stmt.executeUpdate(sql1); 
  16.                 } 
  17.         } 
  18.         catch(SQLException|ClassNotFoundException|IOException e) 
  19.         { 
  20.             e.printStackTrace(); 
  21.         } 
  22.         finally 
  23.         { 
  24.             if(stmt!= null)   
  25.                 stmt.close();         
  26.             if(conn!= null)   
  27.                 conn.close();   
  28.         } 
  29.    } 

然后是一个将可以修复的词修复的方法

 

 

[java] view plaincopy
 
  1. public void modify(ResultSet rs,String str,String reg) throws SQLException 
  2.    { 
  3.        
  4.        Connection conn=null
  5.        Statement stmt=null
  6.        Statement stmt1=null
  7.        try{                   
  8.             conn=Good.getConnection(); 
  9.             stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE 
  10.                     , ResultSet.CONCUR_UPDATABLE); 
  11.             stmt1= conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE 
  12.                     , ResultSet.CONCUR_UPDATABLE); 
  13.             String ok=null
  14.             if(str.indexOf(reg)==str.length()-1
  15.             { 
  16.                  ok=str.substring(0,str.indexOf(reg)); 
  17.                  System.out.println(ok); 
  18.                  System.out.println(ok); 
  19.                  System.out.println(1); 
  20.             } 
  21.             else if(str.indexOf(reg)==0
  22.             { 
  23.                  ok=str.substring(1); 
  24.                  while(ok.indexOf(reg)!=-1
  25.                       ok=ok.substring(1); 
  26.                  System.out.println(2); 
  27.             } 
  28.             else 
  29.             { 
  30.                 System.out.println(3); 
  31.                 System.out.println(str); 
  32.                 ok=str.substring(0,str.indexOf(reg)); 
  33.                  
  34.             } 
  35.             System.out.println(ok); 
  36.             new Good().insert(rs); 
  37.             //String query="select * from cat_keyword where cid='"+rs.getInt("cid")+"'and keyword='"+ok+"'"; 
  38.             String sql="update cat_garbage1 set new='"+ok+"' where id='"+rs.getInt(1)+"'"
  39.             //String sql1="update cat_keyword set keyword='"+ok+"' where id='"+rs.getInt("id")+"'"; 
  40.             stmt.executeUpdate(sql); 
  41.        } 
  42.          
  43.         catch(SQLException|ClassNotFoundException|IOException e) 
  44.         { 
  45.             e.printStackTrace(); 
  46.         } 
  47.         finally 
  48.         { 
  49.             if(stmt!= null)   
  50.                 stmt.close();     
  51.             if(stmt1!= null)   
  52.                 stmt1.close();   
  53.             if(conn!= null)   
  54.                 conn.close();   
  55.         } 
  56.    } 


最后就是一个核心的取词过滤方法,里面有很多正则表达式实现的取词规则。

 

 

[java] view plaincopy
 
  1. public void filt(ResultSet rs) 
  2.     {         
  3.      try 
  4.       { 
  5.         String str;       
  6.         double a=0;double b=0;double c=0;double d=0
  7.         int num=0
  8.         Good good=new Good(); 
  9.         while(rs.next()) 
  10.        {     
  11.         str=rs.getString("keyword"); 
  12.         if(str.equals(",")|str.equals(".")|str.equals(":")|str.equals("-")|str.equals("=")|str.equals("+")|str.equals("*")|str.equals("/")|str.equals("?")|str.equals("|")|str.equals("\\")|str.equals("%")|str.equals("#")|str.equals("!")||str.equals("~")||str.equals("、")) 
  13.         { 
  14.             good.insert(rs); 
  15.             a++; 
  16.         } 
  17.         //字符串后面带逗号 
  18.         if(rule(str,"^\\S+[,]$").matches()) 
  19.         { 
  20.             good.modify(rs,str,","); 
  21.             num++; 
  22.         } 
  23.         //字符串后面带句号 
  24.         if(rule(str,"^\\S+[.]$").matches()) 
  25.         { 
  26.             good.modify(rs,str,"."); 
  27.             num++; 
  28.         } 
  29.         //字符串前面带句号 
  30.         if(rule(str,"^[.]\\S+$").matches()) 
  31.         { 
  32.             System.out.println(123); 
  33.             if(str.indexOf(".net")==-1
  34.             { 
  35.                 if(str.indexOf(".com")==-1
  36.                 { 
  37.                     if(str.indexOf(".cn")==-1
  38.                     { 
  39.                         if(str.indexOf(".org")==-1
  40.                         { 
  41.                             good.modify(rs, str, "."); 
  42.                             num++; 
  43.                         } 
  44.                     } 
  45.                 } 
  46.             } 
  47.         } 
  48.         //字符串后面带- 
  49.         if(rule(str,"^\\S+[-]$").matches()) 
  50.         { 
  51.             good.modify(rs, str, "-"); 
  52.             num++; 
  53.         } 
  54.         //字符串前面带- 
  55.         if(rule(str,"^[-]\\S+$").matches()) 
  56.         { 
  57.             good.modify(rs, str, "-"); 
  58.             num++; 
  59.         } 
  60.         //字符串前面带冒号 
  61.         if(rule(str,"^[:]\\S+$").matches()) 
  62.         { 
  63.             good.modify(rs, str, ":"); 
  64.             num++; 
  65.         } 
  66.         //字符串后面带冒号 
  67.         if(rule(str,"^\\S+[:]$").matches()) 
  68.         { 
  69.             good.modify(rs, str, ":"); 
  70.             num++; 
  71.         } 
  72.         //字符串后面带/ 
  73.         if(rule(str,"^\\S+[/]$").matches()) 
  74.         { 
  75.             good.modify(rs, str, "/"); 
  76.             num++; 
  77.         } 
  78.         //字符串前面带/ 
  79.         if(rule(str,"^[/]\\S+$").matches()) 
  80.         { 
  81.             good.modify(rs, str, "/"); 
  82.             num++; 
  83.         } 
  84.         //字符串后面带? 
  85.         if(rule(str,"^\\S+[?]$").matches()) 
  86.         { 
  87.             good.modify(rs, str, "?"); 
  88.             num++; 
  89.         } 
  90.         //字符串前面带? 
  91.         if(rule(str,"^[?]\\S+$").matches()) 
  92.         { 
  93.             good.modify(rs, str, "?"); 
  94.             num++; 
  95.         } 
  96.         //字符串前面带| 
  97.         if(rule(str,"^[|]\\S+$").matches()) 
  98.         { 
  99.             good.modify(rs, str, "|"); 
  100.             num++; 
  101.         } 
  102.         //字符串后面带| 
  103.         if(rule(str,"^\\S+[|]$").matches()) 
  104.         { 
  105.             good.modify(rs, str, "|"); 
  106.             num++; 
  107.         } 
  108.         //字符串前面带( 
  109.         if(rule(str,"^[(][\\S\\s]+$").matches()) 
  110.         { 
  111.             if(rule(str,"^[(]\\S+[)]\\S*$").matches()) 
  112.             { 
  113.                 str=str.replaceAll("\\)"" "); 
  114.                 good.modify(rs, str, "("); 
  115.                 num++; 
  116.             } 
  117.             else 
  118.             { 
  119.                 good.modify(rs, str, "("); 
  120.                 num++; 
  121.             } 
  122.         } 
  123.         //字符串前面带[ 
  124.         if(rule(str,"^[\\[][\\S\\s]+$").matches()) 
  125.         { 
  126.             if(rule(str,"^[\\[]\\S+[\\]]\\S*$").matches()) 
  127.             { 
  128.                 str=str.replaceAll("\\]"" "); 
  129.                 good.modify(rs, str, "["); 
  130.                 num++; 
  131.             } 
  132.             else 
  133.             { 
  134.                 good.modify(rs, str, "["); 
  135.                 num++; 
  136.             } 
  137.         } 
  138.         //字符串后面带)或者里面带() 
  139.         if(rule(str,"^\\S+\\s*\\S+[)]$").matches()) 
  140.         { 
  141.             System.out.println("qwe"); 
  142.             if(rule(str,"^\\S+[(]\\S+[)]$").matches()) 
  143.             { 
  144.                 str=str.replaceAll("\\("" "); 
  145.                 good.modify(rs, str, ")"); 
  146.                 num++; 
  147.             } 
  148.             else if(rule(str,"^\\S+\\s*[(]\\S+[)]$").matches()) 
  149.             { 
  150.                 str=str.replaceAll("\\("""); 
  151.                 good.modify(rs, str, ")"); 
  152.                 num++; 
  153.             } 
  154.             else 
  155.                 { 
  156.                     good.modify(rs, str, ")"); 
  157.                     num++; 
  158.                 } 
  159.         } 
  160.         //字符串后面带]或者里面带[] 
  161.                 if(rule(str,"^\\S+\\s*\\S+[\\]]$").matches()) 
  162.                 { 
  163.                     System.out.println("qwe"); 
  164.                     if(rule(str,"^\\S+[\\[]\\S+[\\]]$").matches()) 
  165.                     { 
  166.                         str=str.replaceAll("\\["" "); 
  167.                         good.modify(rs, str, "]"); 
  168.                         num++; 
  169.                     } 
  170.                     else if(rule(str,"^\\S+\\s*[\\[]\\S+[\\]]$").matches()) 
  171.                     { 
  172.                         str=str.replaceAll("\\["""); 
  173.                         good.modify(rs, str, "]"); 
  174.                         num++; 
  175.                     } 
  176.                     else 
  177.                         { 
  178.                             good.modify(rs, str, "]"); 
  179.                             num++; 
  180.                         } 
  181.                 } 
  182.         //字符串内包含书名号 
  183.         if(rule(str,"^[\\s\\S]*[《][\\s\\S]+[》]").matches()) 
  184.         { 
  185.             str=str.replaceAll("》"" "); 
  186.             good.modify(rs, str, "《"); 
  187.             num++; 
  188.         } 
  189.         //字符串内包含中文() 
  190.         if(rule(str,"^[\\s\\S]*[(][\\s\\S]+[)]").matches()) 
  191.         { 
  192.             str=str.replaceAll("("" "); 
  193.             good.modify(rs, str, ")"); 
  194.             num++; 
  195.         } 
  196.         //纯数字 
  197.         if(rule(str,"^[1-9]*|0$").matches()) 
  198.         { 
  199.             good.insert(rs); 
  200.             b++; 
  201.         } 
  202.         //单字母 
  203.         if(rule(str,"^[a-zA-Z]$").matches()) 
  204.         { 
  205.             int flag=0
  206.             String shit=rs.getString(3); 
  207.             for(int i=0;i<shit.length();i++) 
  208.                 { 
  209.                     if(str.charAt(0)!=shit.charAt(i))                 
  210.                     flag++;                           
  211.                     if(flag==shit.length()) 
  212.                     { 
  213.                         good.insert(rs); 
  214.                         c++;                         
  215.                     }                 
  216.                 } 
  217.         } 
  218.         //单汉字 
  219.         if(rule(str,"^[\u4e00-\u9fa5]$").matches()) 
  220.         { 
  221.             int flag=0
  222.             String shit=rs.getString(3); 
  223.             for(int i=0;i<shit.length();i++) 
  224.             {                 
  225.                 if(str.charAt(0)!=shit.charAt(i))                                         
  226.                 flag++;                                                   
  227.                 if(flag==shit.length()) 
  228.                 { 
  229.                     good.insert(rs); 
  230.                     d++;                         
  231.                 }                                     
  232.             }                     
  233.         } 
  234.       } 
  235.         System.out.println("单标点百分比:"+100*a/2046036+"%"); 
  236.         System.out.println("纯数字百分比:"+100*b/2046036+"%"); 
  237.         System.out.println("单字母百分比:"+100*c/2046036+"%"); 
  238.         System.out.println("单汉字百分比:"+100*d/2046036+"%"); 
  239.         System.out.println(num); 
  240.         } 
  241.         catch(SQLException e) 
  242.         { 
  243.             e.printStackTrace(); 
  244.         }     
  245.          
  246.     } 

下面是程序的主方法

 

 

[java] view plaincopy
 
  1. public static void main(String[] args) throws SQLException   
  2.     { 
  3.         Connection conn=null
  4.         Statement stmt=null
  5.         try
  6.             long a=System.currentTimeMillis(); 
  7.             ResultSet rs; 
  8.             conn=Good.getConnection(); 
  9.             stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE 
  10.                     , ResultSet.CONCUR_UPDATABLE); 
  11.             Good go=new Good(); 
  12.             /*for(int i=0;i<205;i++) 
  13.             { 
  14.                 //String sql="select * from cat_keyword order by id limit "+i*10001+",10000";            
  15.                 String best="select * from cat_keyword where id>=(select id from cat_keyword order by id limit "+i*10001+",1)limit 10000"; 
  16.                 rs=stmt.executeQuery(best); 
  17.                 go.filt(rs); 
  18.             }*/ 
  19.             String sql="select * from cat_keyword"
  20.             rs=stmt.executeQuery(sql); 
  21.             go.filt(rs); 
  22.             long b=System.currentTimeMillis(); 
  23.             System.out.println("耗时: "+(b-a)/60000+"分钟"); 
  24.             } 
  25.         catch(ClassNotFoundException|SQLException|IOException e) 
  26.         { 
  27.             e.printStackTrace(); 
  28.         } 
  29.         finally 
  30.         { 
  31.             if(stmt!= null)   
  32.                 stmt.close();         
  33.             if(conn!= null)   
  34.                 conn.close();   
  35.         } 
  36.     } 

用一个SQL语句,将整个表的数据一次性作为参数传给负责取词过滤的filt()方法,然后利用ResultSet rs这个指针依次向下对每个词进行处理, 这个方案运行下来处理完全表204万记录只需11分钟,而是用优化之后的limit语句获得的结果集再传给filt()方法那个方案,却需要26分钟。可见使用JDBC,直接传入所有数据的结果集,比使用limit多次限量导入数据要快的多,而且不止是一倍的关系。前者11分钟完胜后者的26分钟。





收藏 推荐 打印 | 录入: | 阅读:
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款