面试准备:海量数据的处理方式

2023-11-12

背景

海量数据的处理主要包括三个方面:

  1. 数据排序
  2. 数据统计
  3. 数据计算

我们可以简单的来算算 5亿个数在内存中的占用:
(64bit)*5*1e8 约为(按1000换算) 4Gbyte,所以内存一次一般装不下。对于这类大数的处理,本文会总结一些方法。

数据排序

分治

  1. 根据数据存在文件中的位置分裂文件到批量小文件中

这里我们的做法是每次读取待排序文件的1e4个数据,把这1e4个数据进行快速排序,再写到一个小文件bigdata.part.i.sorted中。这样我们就得到了5*1e4个已排序好的小文件了。

在有已排序小文件的基础上,我只要每次拿到这些文件中当前位置的最小值就OK了(小顶堆)。再把这些值依次写入bigdata.sorted中。

  1. 根据数据自身大小分裂文件到批量小文件中

按照数据位置进行分裂大文件也可以。不过这样就导致了一个问题,在把小文件合并成大文件的时候并不那么高效。那么,这里我们就有了另一种思路:我们先把文件中的数据按照大小把到不同的文件中。再对这些不同的文件进行排序。这样我们可以直接按文件的字典序输出即可

当然这种做法也会有缺陷,比如如果数据是稠密的(在某一个文件里很多),就不知道把某一个数据放到哪了。

上面的做法需要频繁地读写磁盘,可以设置输入缓存和输出缓存来解决这个问题。为每个拆分节点都设置一个输入缓存,每次将一部分数据读入输入缓存中,只有当输入缓存数据为空时才再从磁盘读入数据。并设置一个输出缓存,只有输出缓存满时才将数据写出磁盘中。

字典树

Trie 树又叫字典树、前缀树和单词查找树,它是一颗多叉查找树,键不是直接保存在节点中,而是由节点在树中的位置决定。

如果海量数据是字符串,可以使用 Trie 树来完成排序操作。先读入海量字符串数据构建一个 Trie 树,最后按字典序先序遍历 Trie 树就能得到已排序的数据。为了处理数据重复问题,可以使用 Trie 树的节点存储计数信息。

数据去重

哈希

考虑到海量数据,需要使用拆分的方式将数据拆分到多台机器。拆分过程可以用哈希取模实现。

压缩存储空间

  1. BitSet
    BitSet存储。如果海量数据是整数且范围不大时,可以使用BitSet存储,通过构建一定大小的比特数组就可以判断某个整数是否出现。
  2. 布隆过滤器
    参考:Redis缓存击穿解决方案
  3. 字典树
    同理。

面试题汇总

以下的题均是海量数据下的解法,后文不做赘述。

1. TopK

问题:
一亿个数查找最大的K个。

解法:

使用大小为K的小顶堆。分为建堆的过程和之后不断reBuildHeap的过程,总的来说复杂度是O(N),前面建堆的复杂度可以忽略不计。

2. 查找中位数

方法一:
分治法的思想是把一个大的问题逐渐转换为规模较小的问题来求解。

对于这道题,顺序读取这 5 亿个数字,对于读取到的数字 num,如果它对应的二进制中最高位为 1,则把这个数字写到 f1 中,否则写入 f0 中。通过这一步,可以把这 5 亿个数划分为两部分,而且 f0 中的数都大于 f1 中的数(最高位是符号位)。

划分之后,可以非常容易地知道中位数是在 f0 还是 f1 中。假设 f1 中有 1 亿个数,那么中位数一定在 f0 中,且是在 f0 中,从小到大排列的第 1.5 亿个数与它后面的一个数的平均值。

提示,5 亿数的中位数是第 2.5 亿与右边相邻一个数求平均值。若 f1 有一亿个数,那么中位数就是 f0 中从第 1.5 亿个数开始的两个数求得的平均值。
对于 f0 可以用次高位的二进制继续将文件一分为二,如此划分下去,直到划分后的文件可以被加载到内存中,把数据加载到内存中以后直接排序,找出中位数。

注意,当数据总数为偶数,如果划分后两个文件中的数据有相同个数,那么中位数就是数据较小的文件中的最大值与数据较大的文件中的最小值的平均值。

方法二:
排序后找。

3. 随机选择K个数

问题:
“给出一个数据流,这个数据流的长度很大或者未知。并且对该数据流中数据只能访问一次。请写出一个随机选择算法,使得数据流中所有数据被选中的概率相等。”

解法:
蓄水池采样(Reservoir Sampling)算法。

介绍该算法之前,我们首先从最简单的例子出发(只在数据流中取一个数据):假设数据流只有一个数据。我们接收数据,发现数据流结束了,直接返回该数据,该数据返回的概率为1。看来很简单,那么我们试试难一点的情况:假设数据流里有两个数据。

我们读到了第一个数据,这次我们不能直接返回该数据,因为数据流没有结束。我们继续读取第二个数据,发现数据流结束了。因此我们只要保证以相同的概率返回第一个或者第二个数据就可以满足题目要求。因此我们生成一个0到1的随机数R,如果R小于0.5,我们就返回第一个数据,如果R大于0.5,返回第二个数据。

接着我们继续分析有三个数据的数据流的情况。为了方便,我们按顺序给流中的数据命名为1、2、3。我们陆续收到了数据1、2。和前面的例子一样,我们只能保存一个数据,所以必须淘汰1和2中的一个。应该如何淘汰呢?不妨和上面例子一样,我们按照二分之一的概率淘汰一个,例如我们淘汰了2。继续读取流中的数据3,发现数据流结束了,我们知道在长度为3的数据流中,如果返回数据3的概率为1/3,那么才有可能保证选择的正确性。也就是说,目前我们手里有1、3两个数据,我们通过一次随机选择,以1/3的概率留下数据3,以2/3的概率留下数据1。那么数据1被最终留下的概率是多少呢?

数据1被留下概率:(1/2)* (2/3) = 1/3
数据2被留下概率:(1/2)*(2/3) = 1/3
数据3被留下概率:1/3

这个方法可以满足题目要求,所有数据被留下返回的概率一样。

因此,循着这个思路,我们可以总结算法的过程

  1. 假设需要采样的数量为K。
  2. 首先构建一个可容纳 K 个元素的数组,将序列的前 K 个元素放入数组中。

然后对于第J( j > k j>k j>k)个元素开始,以 k j \frac{k}{j} jk 的概率来决定该元素是否被替换到数组中(数组中的 K个元素被替换的概率是相同的)。 当遍历完所有元素之后,数组中剩下的元素即为所需采取的样本。

代码如下:

    private int[] sampling(int K) {
        int[] result = new int[K];
        for (int i = 0; i < K; i++) { // 前 K 个元素直接放入数组中
            result[i] = pool[i];
        }

        for (int i = K; i < N; i++) { // K + 1 个元素开始进行概率采样
            int r = random.nextInt(i + 1);
            // 这里其实就是k/j的体现
            if (r < K) {
                result[r] = pool[i];
            }
        }

        return result;
    }

4. 找出出现次数最多的IP

可以考虑采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试准备:海量数据的处理方式 的相关文章

  • 电影下载资源总结

    电驴电骡 donkey4u com emul软件 BT kickass to kat ph isohunt com www torrentkitty com thepiratebay sx thepiratebay ee 论坛 cmct c
  • python绘制三维图

    一 初始化 假设已经安装了matplotlib工具包 利用matplotlib figure Figure创建一个图框 1 2 3 4 import matplotlib pyplot as plt from mpl toolkits mp
  • Elasticsearch 5.6.5 基础笔记(一) - 概念和安装

    概念 Elasticsearch 分布式 可扩展 实时的搜索与数据分析引擎 建立在全文搜索引擎库 Apache Lucene 基础之上 能胜任上百个服务节点的扩展 并支持 PB 级别的结构化或者非结构化数据 将所有的功能打包成一个单独的服务
  • 动态数组的创建与维护

    说是动态数组 其实就是在满容量时 再创建创建一个一定容量的数组 实例代码中是原数组容量的一倍 并将对数组的引用指向新的数组 而当数组容量比较小时 则创建一个一定容量的数组 示例代码中是原数组容量的1 4 并将对数组的引用指向新的数组 示例代

随机推荐

  • Vulkan-程序结构

    程序结构 一般来说 完整的Vulkan程序包含 创建Vulkan实例 获取物理设备列表创建逻辑设备 创建命令缓冲 获取设备中支持图形工作的队列 初始化交换链 创建深度缓冲 创建渲染通道 创建帧缓冲 创建绘制对象 初始化渲染管线 创建栅栏和初
  • Qt获取wifi列表,连接wifi后获取IP地址

    环境win7 qt5 13 MinGW32 台式机 直接上步骤了 网上看到的略显啰嗦 就是这么简单直接 1 头文件 include windows h include wlanapi h 2 pro设置连接路径 需要根据自己安装路径加载 L
  • 要成为一名成功的网络爬虫开发者,需要了解哪些知识点?

    要成为一名成功的网络爬虫开发者 您需要掌握以下一些关键知识 编程语言 Python 是最常用的编程语言之一 特别适合网络爬虫开发 您需要掌握 Python 的基础语法 数据结构和面向对象编程 HTTP 和网络基础知识 了解 HTTP 请求和
  • React之条件渲染(学习和总结)

    在实际开发中经常会遇到条件渲染 一般都是通过if else 语句 三元运算符 switch case 语句来实现 这里记录并学习一下 1 条件渲染之 IF const users id 1 firstName Robin lastName
  • 高精度加法c语言,C语言实现高精度加法

    免费资源网 https freexyz cn 本篇为高精度加法的计算 接下来我还会去写高精度乘法的计算 一 高精度运算的概念 高精度运算其实就是参与运算的数完全超出基本数据类型所能表示的范围的运算 例如int型范围就是 2147483648
  • 深度卷积神经网络(CNN)

    CNN简述 卷积神经网络 Convolutional Neural Network CNN 它是属于前馈神经网络的一种 其特点是每层的神经元节点只响应前一层局部区域范围内的神经元 全连接网络中每个神经元节点则是响应前一层的全部节点 一个深度
  • 信号完整性分析基础知识之有损传输线、上升时间衰减和材料特性(三):耗散因子Df

    在低频下 介电材料的漏电阻是恒定的 用体积电导率来描述材料的电性能 这种体积电导率与材料中离子的密度和迁移率有关 在高频下 由于偶极子的运动增加 电导率随频率增加 材料中可以旋转的偶极子越多 材料的体积电导率就越高 偶极子可以随着施加的场移
  • C++类成员函数可以访问同类不同对象的私有成员

    example 如下例 class Test public Test int v val v Test const Test t val 100 cout lt lt t val lt lt endl void show Test a co
  • Ubuntu识别USB设备

    参考 如何解决Ubuntu无法识别USB设备 作者 一只青木呀 发布时间 2020 08 28 21 02 00 网址 https blog csdn net weixin 45309916 article details 10828682
  • border-style的outset属性在导航中的应用

    代码如下
  • JAVA生成二维码

    一 引入依赖
  • Linux进程管理

    一 Linux下的进程 每个用户均可同时运行多个程序 为了区分每一个运行的程序 Linux给每个进程都做了标识 称为进程号 process ID 每个进程的进程号是唯一的 Linux 给每个进程都打上了运行者的标志 用户可以控制自己的进程
  • 一文看尽2018全年AI技术大突破

    安妮 夏乙 发自 凹非寺量子位 出品 公众号 QbitAI 2018 仍是AI领域激动人心的一年 这一年成为NLP研究的分水岭 各种突破接连不断 CV领域同样精彩纷呈 与四年前相比GAN生成的假脸逼真到让人不敢相信 新工具 新框架的出现 也
  • C++ STL学习网站

    STL教程 C STL快速入门 非常详细
  • java web项目中 Log4j 的配置

    1 引入jar包 log4j 1 2 14 jar 2 在web工程中的web xml文件中新增如下配置
  • 润和HCIP认证套件烧写镜像失败的问题解决

    为了学习OpenHarmony小型和标准设备的开发 买了润和的HCIP认证套件进行开发 按照https device harmonyos com cn docs documentation guide ide hi3516dv300 com
  • ora-12592 TNS:包错误

    导入数据发生 ora 12592 TNS 包错误 网上搜寻资料发现原因是导入时间长导致防火墙触发了 解决方法 1 关掉防火墙尝试导入 2 如果是用本地客户端导入可以尝试到服务器上导入 3 在数据库服务端和客户端配置sqlnet ora文件
  • Access、SQLite、HSQLDB、Sybase、MySQL、DB4O比较

    本文转自 http blog sina com cn s blog 465bc6c90100eums html 一 Access 数据类型有些另类 而且密码太容易被攻破 性能不高 只能用在Windows程序上 一般说来 单个表不超过10万少
  • Latex表和图的显示、引用和并列

    一 表 1 1表的生成 一般我在写论文时 会直接用https www tablesgenerator com生成表的latex编译代码 一般的编译代码如下 begin table htbp begin center caption 标题 l
  • 面试准备:海量数据的处理方式

    文章目录 背景 数据排序 分治 字典树 数据去重 哈希 压缩存储空间 面试题汇总 1 TopK 2 查找中位数 3 随机选择K个数 4 找出出现次数最多的IP 背景 海量数据的处理主要包括三个方面 数据排序 数据统计 数据计算 我们可以简单