【摘要】
本文分析大文件计算的实现原理,如过滤、聚合计算、添加计算列、排序、分组聚合、topN 等,以及利用并行计算来提高计算速度,并用 esProc SPL 举例说明如何用简洁的脚本实现大文件计算。请点击大文件上的结构化数据计算示例了解详情

在数据分析过程中,经常会处理文本文件中的结构化数据(txt,csv等),有时这些文件还会很大,计算机内存不足以一次性读入。这时,只能将数据分批读入内存,对每批数据计算出临时中间结果,分批处理完以后,再按照计算要求对分批处理结果进行恰当的汇总处理,与一次性装入内存的小文件数据计算有很大的不同。

实现大文件计算需要了解一个重要的概念—游标。我们以前比较熟知的是数据库游标,在数据库中使用游标,可以每次返回部分数据,而不将所有数据同时读入内存。游标类似于一个指针,在读取时会通过移动指针的位置来从结果集中每次提取部分记录。与数据库游标类似,在读取大文件数据时,也需要实现文件游标,它具有以下特点:

1、只用于获取数据,并不用来修改结果集。

2、在读取数据时从前向后只遍历一次。

有了游标对象,就可以把大文件计算步骤依次附加在游标对象上,在进行最后计算时,再逐条取出记录,按附加的步骤进行计算。

本文将以结构化文本文件为例,给出大文件过滤、聚合计算、添加计算列、排序、分组聚合、topN 以及并行计算等目标任务的实现方法,并提供用 esProc SPL 编写的代码示例。esProc 是专业的数据计算引擎,其采用的 SPL 中有完善的游标对象及运算,处理这些运算非常方便。

1. 过滤

过滤就是设置一个条件表达式,然后用每条记录的数据来计算表达式的值,如果计算结果值为真则本条记录有效,需要添加到最后取数的结果集里,否则就丢弃这条记录不用取出。对大文件过滤是一种延迟计算,就是先把过滤表达式记在游标对象上,等到取某条记录时,再计算过滤表达式来决定是否将本记录加入结果集。

示例:在大数据学生成绩文本文件students_scores.txt中,查找10班学生的成绩。列数据间用TAB分隔,部分数据如下图:

esProc SPL脚本如下:

2. 聚合计算

聚合计算是对大文件中的所有记录,执行某种统计计算,比如统计总和、平均值、最大值、最小值、计数等。循环遍历游标中所有记录,用每条记录数据计算出当前的聚合统计值,只把统计值存在内存中,而不用保存数据记录,就不会占据太多内存。遍历完毕后就得到最终的统计值。

示例:在大数据学生成绩文本文件students_scores.csv中,列数据间用逗号分隔,部分数据如下图:

计算语文成绩总分,esProc SPL脚本如下:

计算10班语文成绩总分,esProc SPL脚本如下:

3. 添加计算列

添加计算列是指用文件中的一列或几列经过某种指定计算,将计算结果记为一个新列的列值。这也是一种延迟计算,当读取某条记录时,再计算表达式的值,将它赋给本记录的新列。

示例:在大数据学生成绩文本文件students_scores_.txt中,列数据间用|分隔,部分数据如下图:

计算每位学生的总成绩,esProc SPL脚本如下:

除了用derive增加新列,也可以用new函数创建新的数据结构,同时也可以增加新的列,例如:

当然,也可以先对数据进行过滤,再对需要的记录产生新列或生成新的结构。例如只取出10班的学生成绩并新增总成绩列,esProc SPL脚本如下:

在获取到最终计算结果之前,各种基本计算,如过滤、新增列、产生新结构、改变字段值、排序等,都可以按需求先后附加到游标上。后面小节的示例中就不再一一列举这些了,只列出小节所讲的主题计算。

4. 排序

大文件排序因内存不足,不能读入所有数据来排序,实现的原理是这样的:先读入一批数据记录,读多少行合适要根据内存而定,将这批数据排序后存到一个临时文件,再读入下一批数据排序后存到另一个临时文件……直到所有数据处理完,最后对这些临时文件进行有序归并——读出每个临时文件的第一行,通过对排序字段值的比较,找出应该排在最前面的那一行,写入到结果文件。然后从刚才排第一的那个临时文件中再读出下一行,继续比较找出最前面的一行写入结果文件。按此方法不断进行,直到所有数据行都写入结果文件。

示例:在大数据学生成绩文本文件students_scores.txt中,按语文成绩升序排列。

esProc SPL脚本如下:

也可以同时按多个字段排序或按表达式计算值排序,如将A2单元格改为:

=A1.sortx(Chinese,Math) //按语文、数学成绩先后排序

=A1.sortx(Math+English+Chinese) //按总成绩排序

5. 分组聚合

分组聚合是先对数据记录进行分组,对同一组的记录进行某种统计计算,最后得到每一组的统计值。大文件的分组聚合分两种情况:一是分组的结果不大(组数少),所有分组结果都能在内存中放下,称之为小分组聚合;二是分组的结果很大(组数非常多),内存中存不下所有的组,称之为大分组聚合。

小分组聚合的实现原理是:把分组键值和组统计值保存在内存中,在读取每条记录时,按分组表达式计算出分组键值,在保存的组里查找此键值,找到了则将本记录的数据与组统计值汇总,没找到则新加入一个组。最后直到所有行都处理完,就得到了所有的分组和本组的统计值。

示例:在大数据用户登录记录文件user_info_reg.csv中,统计各省用户的登录总次数及总时长。列数据间用逗号分隔,部分数据如下图:

esProc SPL脚本如下:

大分组聚合因内存不足,不能把所有分组聚合的结果放在内存里,所以需要分批处理,并使用临时文件保存分批结果,最后再归并汇总,实现原理是这样的:逐行读入数据,按照小分组聚合的流程进行分组聚合,当保存的分组结果集大到一定程序时(结果集大小视内存决定),将此结果集按分组键值排序后存为临时文件,从内存中清除。继续读入数据作同样处理,当所有数据处理完以后,就得到了多个按分组键值排好序的临时文件。然后对这些临时文件的数据作有序归并(与大文件排序的归并流程相同),得到一个按分组键值排序、键值很可能有重复的大文件,最后把那些重复键值的组合并成一组,得到所有分组结果大文件,再返回用此文件创建的游标供调用者提取分组结果数据。

示例:在大数据用户登录记录文件user_info_reg.csv中,统计每个用户的登录总次数及总时长。

esProc SPL脚本如下:

6. TopN

TopN是对数据排序以后,查出前N条记录。有时需要对所有数据求前N条记录,有时还需要先对数据分组,再求每一组中的前N条记录。

但计算TopN时其实不需要对所有数据排序,那样会在排序上花费很多时间,对大文件计算尤其如此。TopN的实现原理是这样的:先读出N条记录,形成一个N条记录的小数据集并排好序,再读新的记录时,与小数据集的最后一条比较,若排在它之后,则直接丢弃这条记录,若排在它之前,则将这条新记录插入到小数据集的合适位置,丢弃小数据集的最后一条记录。当所有数据都读出并处理完时,就得到了需要的前N条记录集。TopN的实现方式和聚合运算很像。

示例:在大数据学生成绩文本文件students_scores.txt中,查找数学成绩排在前10的学生记录。

esProc SPL脚本如下:

top函数除了返回前N条记录,也可以返回前N个值。例如查找排在前10的数学成绩,esProc SPL脚本如下:

TopN还可以使用到分组中,即每个组中取TopN,其计算原理也类似,只是需要为每个分组保持一个N条记录的小数据集。

示例:在大数据学生成绩文本文件students_scores.txt中,查找各班数学成绩排在前10的学生记录。

esProc SPL脚本如下:

7. 并行提速

并行计算就是用多个线程同时分担一个计算任务,能充分利用多核CPU提高计算性能,这对于大文件特别有用。大文件计算常常需要将数据分批计算,最后再将分批计算结果进行合并汇总。并行计算也是如此,先将大文件分段,每个线程各自用大文件计算的方式处理一段数据,最后将各线程处理的结果进行汇总。示例:在大数据用户登录记录文件user_info_reg.csv中,统计各省用户的登录总次数,用4路并行计算提高速度。esProc SPL脚本如下:

示例:在大数据学生成绩文本文件students_scores.csv中,查询各班语文成绩在90分以上且总成绩排在前5名的学生,并用8路并行提高速度,esProc SPL脚本如下:

通过以上示例可以看出,在SPL中使用并行提速非常容易,与单线程代码相比,仅仅多一个游标选项与参数,让用户使用并行非常方便。

《SPL CookBook》中有更多敏捷计算示例。

按一行一行的方法将一个文本文件复制到另一个文件中_大文件上的结构化数据计算示例...相关推荐

  1. 按一行一行的方法将一个文本文件复制到另一个文件中_命令行技巧:分割文件内容...

    (给Linux爱好者加星标,提升Linux技能) 英文:Stephen Snow,翻译:Linux中国/MjSeven linux.cn/article-10809-1.html Fedora 发行版 ...

  2. mysql把一个数据库中的数据复制到另一个数据库中的表 2个表结构相同

    1.表结构相同的表,且在同一数据库(如,table1,table2) Sql :insert into table1 select * from table2 (完全复制) insert into t ...

  3. 萌新的Python练习实例100例(七)将一个列表的数据复制到另一个列表中

    题目: 将一个列表的数据复制到另一个列表中 分析: · 这道题是联系list和切片的使用: 方法1: · 将b的值赋予a: · a[0:3]表示使用切片从0位置开始到第3位置结束: · a[:3]表示 ...

  4. php中读取大文件实现方法详解

    php中读取大文件实现方法详解 来源:   时间:2013-09-05 19:27:01   阅读数:6186 分享到:0 [导读] 本文章来给各位同学介绍php中读取大文件实现方法详解吧,有需要了解 ...

  5. 针对SEO优化的网页摘要和结构化数据方法(微数据)

    针对SEO优化的网页摘要和结构化数据方法(微数据) 关于丰富网页摘要和结构化数据 谷歌丰富摘要和结构化数据旨在让Google更了解您网页上的内容,创建丰富网页摘要,为用户具体查询提供更详尽的信息. 丰 ...

  6. “可扩展标记语言”(XML) 提供一种描述结构化数据的方法。

    摘要: "可扩展标记语言"(XML) 提供一种描述结构化数据的方法.与主要用于控制数据的显示和外观的 HTML 标记不同,XML 标记用于定义数据本身的结构和数据类型. XML 使 ...

  7. Python-将一个列表的数据复制到另一个列表中

    # 题目:将一个列表的数据复制到另一个列表中 list1 = [x for x in range(1,5)]list2 = []print(list1)print(list2) #初始化 print( ...

  8. 将数组项复制到另一个数组中

    本文翻译自:Copy array items into another array I have a JavaScript array dataArray which I want to push i ...

  9. C语言 | 将字符串中的元音字母复制到另一个字符串中

    例70:C语言写一个函数,将一个字符串中的元音字母复制到另一字符串,然后输出. 解析:if语句判断一下每一个字母是否符合元音字母,读者看着道题的时候,需要注意一点的是如果用scanf函数是否可以,思考 ...

最新文章

  1. 新手建议学php吗,关于PHP新手学习的一些指导和建议,新手来我的
  2. MySQL—01—MySQL介绍和安装
  3. 图像的打开、修改、显示和保存示例(OpenCV 2.0)
  4. node 微信授权 获取openid
  5. 控制uibutton的title范围
  6. 浏览器指纹实现方案:Cookie、Flash Cookies、帆布指纹识别
  7. pyplot 余弦函数_python如何画出三角函数
  8. MongoDB-与SpringBoot集成
  9. 黑客们成功地在土豆上安装了Linux!
  10. 泛微OA的SQL语句大全
  11. 来自TMDB的5000部电影数据集
  12. mobi格式转换成pdf格式
  13. centos VBoxLinuxAdditions 安装报错 Building the main Guest Additions module
  14. 换硬币 (20 分)Java【循环】
  15. 运动控制器多工位位置比较输出在转盘式视觉筛选设备中的应用
  16. UML 之 C++类图关系全面剖析
  17. 穿越晋商百年-体验非遗文化
  18. Android 工程师进阶手册(8 年 Android 开发者的成长感悟)
  19. 小鹿妹眼中的三亚。告诉你怎么玩三亚
  20. 【云原生之kubernetes实战】在k8s环境下部署OneNav个人书签工具

热门文章

  1. IntelliJ IDEA的黑白色背景切换(Ultimate和Community版本皆通用)
  2. Charles 从入门到精通
  3. 关于OnTouchListener的深入理解
  4. C#入门篇5-6:流程控制语句 foreach
  5. iptraf 打不开
  6. golang 解析html
  7. java rmi 原理和使用浅析
  8. linux centos 7 安装中文字体
  9. docker、k8s 简介
  10. win10 microsoft compatibility telemetry 禁用用户改善反馈服务进程 磁盘占用高