一、由于具有多张宽表且字段较多,每个宽表数据大概为4000万条,根据业务逻辑拼接别名,并每张宽表的固定字段进行left join 拼接SQL。这样就能根据每个宽表的主列,根据每个宽表的不同字段关联出一张新的集合。由于下来要进行分页查询,如果要使用SparkSQL进行分页查询,需要增加序号列,那么就在刚才的Sql之前增加一句 create table tableName as SELECT  ROW_NUMBER() OVER() as id,* from (拼接的SQL) 就可创建一张带自增序列的,业务需要字段的几张宽表的关联集合,方便下来分页。

  1. for(int i=0;i<ColumnNames.size();i++){
  2. SiCustomerLabelInfoModel Column = ColumnNames.get(i);
  3. List<CiMdaSysTable> ciMdaSysTable = ciCustomerJDao.getMdaSysTableName(Column.getColumnName());
  4.  
  5. String alias = "t_" + ciMdaSysTable.get(0).getTableId();
  6. String aliasColumn = alias + "." + Column.getColumnName();
  7. String aliasTable = ciMdaSysTable.get(0).getTableName() +" "+ alias;
  8.  
  9. if(mainTable == null){
  10. mainTable = aliasTable;
  11. }
  12. if(ciMdaSysTable.get(0).getUpdateCycle() == 1){
  13. mainTable = aliasTable;
  14. }
  15.  
  16. ColumnNameList.add(aliasColumn);
  17. tableNameList.add(aliasTable);
  18. }
  19. String[] keyAlias = mainTable.split(" ");
  20. String mainKeyColumn = keyAlias[1] + "." + keyColumn;
  21. selectResult.append("select ").append(mainKeyColumn);
  22. if(StringUtil.isNotEmpty(mainTable)){
  23. fromTableName.append(" from ").append(mainTable);
  24. }
  25. Iterator<String> table = tableNameList.iterator();
  26. while(table.hasNext()){
  27. String tableName = table.next();
  28. String[] tableAlias = tableName.split(" ");
  29. String[] mainAlias = mainTable.split(" ");
  30. String alias = tableAlias[1];
  31. String mAlias = mainAlias[1];
  32.  
  33. if(!mainTable.equals(tableName)){
  34. fromTableName.append(" left join ").append(tableName).append(" on ").append(mAlias).append(".").append(keyColumn)
  35. .append(" = ").append(alias).append(".").append(keyColumn).append(" ");
  36. }
  37. }
            

          fromTableName.append(" ) a");
          Iterator<String> column = ColumnNameList.iterator();
          while(column.hasNext()){
          String columnName = column.next();
          selectResult.append(",").append(columnName);
          }
          selectResult.append(fromTableName);
          Createtable.append("create table ").append(cocDwName).append(" as SELECT ROW_NUMBER() OVER() as id,* from").append(" (").append(selectResult);

  1.  

二、由于业务场景,需要将4000万条数据最终写入10个文件,这里通过声明线程池pool,使用多线程的方法执行,有些人会担心那不会数据错乱吗,不会。因为后面要用分页sql,根据循环传入的 i 的值进行处理。

  1. private ExecutorService pools = Executors.newFixedThreadPool(15);
  2. if(result = true){
  3. String queryCount = "select count(*) from "+cocDwName;
  4. int count = ciCustomerJDao.getDwTotolCount(queryCount);
  5. log.info(""+keyColumn);
  6. try {
  7. for(int i=0;i<10;i++){
  8. CreateDwFileThread jd = new CreateDwFileThread(jndiName,keyColumn,num,cocDwName,count,sysId,i);
  9. Future fu = pools.submit(jd);
  10. fus.add(fu);
  11. }
  12. long start = System.currentTimeMillis();
  13. while (true) {
  14. boolean done = true;
  15. for (Future f : fus) {
  16. if (!f.isDone()) {
  17. done = false;
  18. break;
  19. }
  20. }
  21. if (!done) {
  22. try {
  23. Thread.sleep(1000 * 10);
  24. } catch (InterruptedException e) {
  25. log.error("sleep error", e);
  26. e.printStackTrace();
  27. }
  28. continue;
  29. } else {
  30. break;
  31. }
  32. }
  33. log.debug("wait tasks finish cost:" + (System.currentTimeMillis() - start));
  34.  
  35. }catch(Exception e){
  36. result = false;
  37. log.error("error", e);
  38. }
  39. }

三、根据第一步创建的表中的自增序列ID进行分页,由于要多线程并发执行,所以不能使用传统分页的begin与end,根据步骤二中传入的 i (这里参数为partNumber)进行处理,根据循环,每条线程执行的开始数据必定以上条数据结束的条数为开始,每次将查询出来的结果集通过list2File写入文件。这里还有个while循环,因为分成10份还是有400万条数据啊,还是觉得大,于是就又分成了10次~就是说每次查询出40万条写入文件,直到新加入400万条flag返回true退出循环。

  1. while(flag == false){
  2. pager.setPageSize(bufferedRowSize);
  3. pager.setPageNum(pageNumber);
  4.  
  5. int begin = (pager.getPageNum() - 1) * pager.getPageSize()+createFileCount*partNumber;
  6. int end = begin + pager.getPageSize();
  7. if(end >= createFileCount*(partNumber+1)){
  8. end = createFileCount*(partNumber+1);
  9. }
  10. StringBuffer sql = new StringBuffer() ;
  11. sql.append(" select ").append(columns).append(" from ").append(cocDwName).append(" where id > ").append(begin).append(" and ").append(" id < ").append(end+1);
  12. JdbcBaseDao jdbcBaseDao = (JdbcBaseDao) SystemServiceLocator.getInstance().getService("jdbcBaseDao");
  13. String BackjndiName = PropertiesUtils.getProperties("JNDI_CI_BACK");
  14. final String file = fileLocalPath + File.separator + dwName+ "_" + String.valueOf(partNumber)+ ".csv";
  15. Log.info("---------sql;:"+ sql + "-------fileName:"+file);

              

  1. List<Map<String, Object>> dataList = jdbcBaseDao.getBackSimpleJdbcTemplate().queryForList(sql.toString());
  2.               if (dataList.size() > 0) {
  3.               list2File(dataList, title, columns, file, encode, null, null);
  4.               pageNumber++;
  5.               }
  6.               if(end == createFileCount * partNumber + createFileCount){
  7.               flag = true;
  8.               }

  

有人会问你为啥不用ResultSet 直接放入400万条数据 为啥还要分开每40万条数据再分页写~ 我想说 我就是想这么干~ 啊哈哈。。。不过程序中貌似是有问题的 没有考虑到的情景,所以还在推敲。。(Resultset 查出来400万条不还是放在内存中,还是有可能内存溢出的,分页写大不了通过thriftserver多连接几次spark嘛~ 不过代码写的很烂,还在提高哈~)

使用SparkSQL实现多线程分页查询并写入文件的更多相关文章

  1. mysql查询结果写入文件

    注:转自csdn zuyi532 方法1: shell> mysql -uroot -proot -h localhost xxx库 -e " select * from xxx表 l ...

  2. Linux把查询结果写入到文本

    在Linux命令模式下,可以将查询结果写入文件.大概有两种方式,增量写入和覆盖写入. 增量写入: #iostat -m >> /tmp/iostat.txt 覆盖写入: #iostat - ...

  3. 【CoreData】分页查询和模糊查询

    在CoreData实际使用中,分页查询和模糊查询是必不可少的,接下来演示一下: 首先 // 1.创建模型文件 (相当于一个数据库里的表) // New File ———— CoreData ———— ...

  4. Mybatis包分页查询java公共类

    Mybatis包分页查询java公共类   分页----对于数据量非常大的查询中.是不可缺少的. mybatis底层的分页sql语句因为须要我们自己去手动写.而实现分页显示的时候我们须要依据分页查询条 ...

  5. 【MySQL】分页查询实例讲解

    MySQL分页查询实例讲解 1. 前言 本文描述了团队在工作中遇到的一个MySQL分页查询问题,顺带讲解相关知识点,为后来者鉴.本文的重点不是"怎样"优化表结构和SQL语句,而是探 ...

  6. oracle 12c 新特性之(相同字段上的多重索引、ddl 日志、限制PGA的大小、分页查询)

    1. 相同字段上的多重索引   在Oracle 12c R1之前,一个字段是无法以任何形式拥有多个索引的.或许有人会想知道为什么通常一个字段需要有多重索引,事实上需要多重索引的字段或字段集合是很多的. ...

  7. JAVAEE——BOS物流项目04:学习计划、datagrid、分页查询、批量删除、修改功能

    1 学习计划 1.datagrid使用方法(重要) n 将静态HTML渲染为datagrid样式 n 发送ajax请求获取json数据创建datagrid n 使用easyUI提供的API创建data ...

  8. 【1】MySQL大数据量分页查询方法及其优化

    ---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适应场景: 适用于数据量较少的情况(元组百/千 ...

  9. mysql分库 分页查询

    Mysql海量数据分表分库如何列表分页? 1.现在使用ElasticSearch了.基于Lucene的解决方案 2.必须将mysql里的数据写入到类似hbase这样的分布式数据库,查询快.但分页.查询 ...

随机推荐

  1. POJ 1488 Tex Quotes --- 水题

    POJ 1488 题目大意:给定一篇文章,将它的左引号转成 ``(1的左边),右引号转成 ''(两个 ' ) 解题思路:水题,设置一个bool变量标记是左引号还是右引号即可 /* POJ 1488 T ...

  2. IOS中调用系统的电话、短信、邮件、浏览功能

    iOS开发系列--通讯录.蓝牙.内购.GameCenter.iCloud.Passbook系统服务开发汇总 2015-01-13 09:16 by KenshinCui, 26990 阅读, 35 评 ...

  3. IOS请求H5页面、要求自定义agent判断是电脑、安卓还是iPhone登录

    //自定制的userAgent- (void)createMyAgent{        NSString *userAgent = [[[UIWebView alloc]init]stringByE ...

  4. hdu1025 dp(最长上升子序列LIS)

    题意:有一些穷国和一些富国分别排在两条直线上,每个穷国和一个富国之间可以建道路,但是路不能交叉,给出每个穷国和富国的联系,求最多能建多少条路 我一开始在想有点像二分图匹配orz,很快就发现,当我把穷国 ...

  5. Tyvj 9.10 总结 (其实只是发一下心情)

    原以为能拿200的,然而看到成绩彻底方了,60滚粗,连100都不到 这种成绩连一等都拿不到,我tm还谈什么省选,更别说NOI了 目前还没有部分分版本的,也没有数据,不知道问题出在哪里 tyvj群里好多 ...

  6. Linux-Nginx之sendfile与上下文切换

    今天在看nginx thread pool的时候,频繁的看到sendfile,其实以前也经常看到sendfile,只是我平时选择性的忽视而已... 先说下sendfile,明天在好好聊下nginx 线 ...

  7. 安装postgreSQL出现configure:error:readline library not found解决方法

    要安装 readline , readline-dev 开发包,要么使用 --without-readline 选项关闭 readline 功能. #yum install readline; #yu ...

  8. centos7下环境配置

    1:  安装memcached 问题:error: libevent is required. If it's already installed, specify its path using –w ...

  9. 二十四种设计模式:中介者模式(Mediator Pattern)

    中介者模式(Mediator Pattern) 介绍用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 示例有一个Messa ...

  10. unity 合并skinnedMeshRenderer中遇到的一个大坑

    将多个skinnedMeshRenderer合并成一个skinnedMeshRenderer,主要涉及的mesh合并.骨骼列表合并.重定向顶点骨骼索引.其中重定向顶点骨骼索引只是通过加偏值即可完成,所 ...