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

for(int i=0;i<ColumnNames.size();i++){
SiCustomerLabelInfoModel Column = ColumnNames.get(i);
List<CiMdaSysTable> ciMdaSysTable = ciCustomerJDao.getMdaSysTableName(Column.getColumnName()); String alias = "t_" + ciMdaSysTable.get(0).getTableId();
String aliasColumn = alias + "." + Column.getColumnName();
String aliasTable = ciMdaSysTable.get(0).getTableName() +" "+ alias; if(mainTable == null){
mainTable = aliasTable;
}
if(ciMdaSysTable.get(0).getUpdateCycle() == 1){
mainTable = aliasTable;
} ColumnNameList.add(aliasColumn);
tableNameList.add(aliasTable);
}
String[] keyAlias = mainTable.split(" ");
String mainKeyColumn = keyAlias[1] + "." + keyColumn;
selectResult.append("select ").append(mainKeyColumn);
if(StringUtil.isNotEmpty(mainTable)){
fromTableName.append(" from ").append(mainTable);
}
Iterator<String> table = tableNameList.iterator();
while(table.hasNext()){
String tableName = table.next();
String[] tableAlias = tableName.split(" ");
String[] mainAlias = mainTable.split(" ");
String alias = tableAlias[1];
String mAlias = mainAlias[1]; if(!mainTable.equals(tableName)){
fromTableName.append(" left join ").append(tableName).append(" on ").append(mAlias).append(".").append(keyColumn)
.append(" = ").append(alias).append(".").append(keyColumn).append(" ");
}
}
        

          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);


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

	private ExecutorService pools = Executors.newFixedThreadPool(15);
if(result = true){
String queryCount = "select count(*) from "+cocDwName;
int count = ciCustomerJDao.getDwTotolCount(queryCount);
log.info(""+keyColumn);
try {
for(int i=0;i<10;i++){
CreateDwFileThread jd = new CreateDwFileThread(jndiName,keyColumn,num,cocDwName,count,sysId,i);
Future fu = pools.submit(jd);
fus.add(fu);
}
long start = System.currentTimeMillis();
while (true) {
boolean done = true;
for (Future f : fus) {
if (!f.isDone()) {
done = false;
break;
}
}
if (!done) {
try {
Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
log.error("sleep error", e);
e.printStackTrace();
}
continue;
} else {
break;
}
}
log.debug("wait tasks finish cost:" + (System.currentTimeMillis() - start)); }catch(Exception e){
result = false;
log.error("error", e);
}
}

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

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

              

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

  

有人会问你为啥不用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. C#部分---"++"在前在后的区别。

    int a=5; int b=a++;//int b=a;a=a+1 int c=++a;//a=a+1;int c=a

  2. js调用百度地图API创建地图

    技术交流群:233513714 <html xmlns="http://www.w3.org/1999/xhtml"><head runat="serv ...

  3. Android平台下的JNI开发

    JNI是Java Native Interface的缩写,通过JNI可以方便我们在Android平台上进行C/C++编程.要用JNI首先必须安装Android的NDK,配置好NDK环境之后就可以在Ec ...

  4. socket、webService、RMI ?

    网络七层协议为:物理层.数据链路层.网络层.传输层.会话层.表示层.应用层 webService > RMI > socket RMI比socket更高一点 socket 只是 java在 ...

  5. vb6 判断64位操作系统

    Option Explicit Private Declare Function GetCurrentProcess Lib "kernel32" () As Long Priva ...

  6. 怎么用EDIUS实现跟踪马赛克效果

    我们经常会在一些新闻的视频中看到一些马赛克,这些马赛克一般都是保护人物的隐私权,肖像权什么的.我们时常也会看到即使人物位置发生了变化,被遮挡的地方依旧还是被遮挡住,一点也不用担心因为人物运动而使马赛克 ...

  7. Python 统计IIS日志行数

    __author__ = 'Administrator' import codecs def blocks(file, size=65536): while True: b = file.read(s ...

  8. Q7: Unique Binary Search Trees

    问题描述: Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For ...

  9. 什么是JDK

    Java Development Kit (JDK) 是太阳微系统针对Java开发人员发布的免费软件开发工具包(SDK,Software development kit).JDK 是整个Java的核心 ...

  10. vs2010 release 模式加了断点,跑代码无法跟踪,解决方法

    纯跑代码,不是附加进程调试. 打开不能调试的类库项目属性页面→切换到生成选项卡→点击高级按钮→将调试信息一项设置 将“调试信息”设置为“pdb-only”.  我是按图上的设置就正常了. -- 201 ...