快捷搜索:

当小内存遇上大量数据,你该怎么解决这个问题

原标题:当小内存赶上大年夜量数据,你该怎么办理这个问题?

作者丨ItamarTurner-Trauring

译者丨夏夜

策划丨万佳

当你写了一个处置惩罚数据的软件,它可能在小样本文件上运行地很好,但一旦加载大年夜量真实数据后,这个软件就会崩溃。

问题在于你没有足够的内存——假如你有16GB的RAM,你就无法一次载入100GB大年夜小的文件。载入这么大年夜的文件时,操作系统在某个时候就会耗尽内存,不能分配存储单元,你的法度榜样也就会崩溃。

以是,你该如何防止这类环境发生?你可以启动一个大年夜数据集群——你所必要做的是:

搞到一个谋略机集群。

花一周光阴搭建这个集群。

大年夜部分环境下,你必要进修一套全新的API,重写你所有的代码。

这个价值可能很昂贵,会令人沮丧;幸运的是,大年夜部分环境下,我们不必这样做。

你必要一个简单而轻易的办理规划:在单机上处置惩罚你的数据,最小化情况搭建开销,尽可能使用你正在应用的代码库。实际上,大年夜部分环境你都可以做到这样,只要应用一些措施即可,无意偶尔候这些措施被称为“核外谋略”(out-of-corecomputation)。

本文将先容如下内容:

你究竟为什么必要RAM。

处置惩罚无法放入内存的数据最简单的措施:花些钱。

处置惩罚大年夜量数据的三种基础软件措施:压缩、分块、索引。

之后的文章将会展示若何把这些措施利用到诸如NumPy和Pandas这样的库中。

1你究竟为什么必要RAM?

在我们开始解释办理规划前,我们要弄清楚该问题是若何孕育发生的。我们的谋略机内存(RAM)能让你读写数据,然则你的硬盘也可以读写数据——那为什么谋略机还必要RAM呢?硬盘比RAM更便宜,以是它平日大年夜到能够容纳下你的所稀有据,那为什么你的代码不能直接从硬盘读写数据呢?

理论上讲,这也行得通的。然则,纵然是最今世化且速率很快的SSD硬盘也比RAM慢太多:

从SSD上读取数据:大年夜约1.6万纳秒

从RAM上读取数据:大年夜于100纳秒

假如你想要实现快速谋略,数据就只能放在RAM中,否则你的代码运行时就会慢上150倍。

2资金方面的办理规划:购买更多的RAM

没有足够RAM时的最简单办理规划便是费钱来办理。你要么购买一台谋略机,或者租一台云真个虚拟机(VM:VirtualMachine,这会连大年夜多半条记本电脑贵得多)。2019年11月,我轻细调研了一下,在价格方面做了一些对照,发明你可以这样:

购买一台ThinkpadM720Tower,它有6个核和64GBRAM,价格是1074美金。

租用一台云真个VM,它有64个核和432GBRAM,价格是每小时3.62美金。

这只是我轻细调研后发明的数字,再继承调研下去,你会发明更好的规划。

假如费钱购买硬件可以把你的数据读入RAM,这平日就会是一个最经济的办理规划:终究你的光阴相称宝贵。然则,无意偶尔候,这还不敷办理这个问题。

例如,假如你要运行许多半据处置惩罚义务,在一段时期内,云谋略可能是一个自然能想到的办理规划,但也是一个昂贵的办理规划。曾经在一个事情中,我的软件项目必要的谋略开销险些快用完了我们产品所有的预期收入,包括支付我薪水所需的至关紧张的那部分收入。

假如购买/租用更多的RAM不够以满意需求或者根本行不通时,下一步就应该斟酌若何经由过程改动软件来削减内存应用了。

3技术#1:压缩

压缩意味着用一种不合的表达形式表示你的数据,这种形式能占用更少内存。有两种要领来压缩:

无损压缩:存储的数据包孕的信息和原始数据包孕的信息完全相同。

有损压缩:存储的数据损掉了一些原始数据里的细节信息,然则这种信息损掉抱负环境下不会对谋略结果造成什么影响。

我想阐明的是,我不是在讨论应用ZIP或者gzip对象来压缩文件,由于这些对象平日是对硬盘上的文件进行压缩的。为了处置惩罚ZIP压缩过的文件,你平日必要把这个文件载入内存中再进行解压缩为原始文件大年夜小,以是这着实对内存节省没有什么赞助。

你必要的是内存中的数据压缩表示形式。

例如,比如说你的数据有两个值,一共也只会有两个值:“AVAILABLE”(代表可能取到的值)和“UNAVAILABLE”(代表弗成能取到的值)。我们可以不必将其存为10个或更多字节的字符串,你可以将其存为一个布尔值,用True或者False表示,这样你就可以只用1个字节来表示了。你以致可以继承压缩至1位来表示布尔值,这样就继承压缩到了1个字节时的1/8大年夜小。

4技术#2:分块,每次只加载所稀有据里的某一块

当你必要处置惩罚所稀有据,而又无需把所稀有据同时载入内存时,分块是很有用的。你可以把数据按块载入内存,每次谋略一块的数据(或者正如我们要在往后一篇文章里想评论争论的,可以多块并行处置惩罚)。

例如,比如说,你想搜索一本书里的最长单词。你可以一次性将所稀有据载入内存:

largest_word=""forwordinbook.get_text.split:iflen(word)>len(largest_word):largest_word=word

然则在我们的例子中,这本书太大年夜而不能完全载入内存,这时刻你就可以一页一页地载入这本书。

largest_word=""forpageinbook.iterpages:forwordinpage.get_text.split:iflen(word)>len(largest_word):largest_word=word

这样你应用的内存就大年夜大年夜削减了,由于你一次只必要把这本书的一页载入内存,而着末获得的结果仍旧是精确的。

5技术#3:当你必要数据的一个子集时,索引会很有用

当你必要数据的一个子集时,索引会很有用,应用索引你可以在不应时候加载数据的不合子集。

你也可以用分块办理这个问题:每次加载所有的数据,过滤掉落你不想要的数据。但这会很慢,由于你加载了很多不相关的数据。

假如你只必要部分数据,不要应用分块,最好应用索引,它可以奉告你到哪里能找出你关心的那部分数据。

想象一下,你只想浏览书籍中关于土豚的章节。假如你运用分块技巧,你得载入整本书,一页一页的载入,每页地征采土豚——但这要花很长光阴才能完成。

或者说,你可以直接涉猎这本书的末端部分,也便是书籍的索引部分,然后找到“土豚”的索引项。它可能会奉告你在第7、19页以及120-123页可以读到相关内容。以是,现在你可以只读那几页,这样就快多了。

这样很有效,由于索引比整本书占用的空间要小很多,以是把索引载入内存找出相关内容所在就会更轻易。

6最简单的索引技术

最简单也最常用的实现索引的措施便是在目录里给文件恰当命名:

mydata/2019-Jan.csv2019-Feb.csv2019-Mar.csv2019-Apr.csv...

假如你想要2019年3月数据,你就只必要加载2019-Mar.csv这个文件——而不用加载2月、7月或者其他任何月份的数据。

7下一步:利用这些技术

RAM不敷用,最简单的办理措施便是费钱买更多的RAM。然则,假如这个规划无法实现或者仍旧不敷用时,你就必要应用压缩、分块或者索引来办理。

这些措施也呈现在其他许多不合的软件包和对象中。纵然是大年夜数据系统也是建立在这些措施之上的:例如应用多个谋略机来处置惩罚分块数据。

在接下来的文章里,我会给你展示若何应用详细的库和对象(NumPy、Pandas,或者用ZIP对象压缩文件)来利用这些措施。假如在我写完这些文章时,你就想涉猎到它们,请鄙人方表格里注册我的通讯简报(newsletter)。

原文链接:

https://pythonspeed.com/articles/data-doesnt-fit-in-memory

滥觞:搜狐

您可能还会对下面的文章感兴趣: