Python还是数据库?

4
我正在将一个CSV文件读入Python的一个列表中。该文件现在大约有100MB大小,但未来几年内可能会增长到2-5GB。我对数据进行了大量的日志计算。目前处理100MB文件需要脚本花费约1分钟时间。脚本对数据进行了许多操作后,将创建指向Google图表的URL,并下载这些图表到本地。
如果文件大小达到2GB,是否应该将数据转移到数据库中,而不是继续使用Python?

你的数据是否会发生变化?换句话说,旧的原始行是否随着时间而改变? - mcpeterson
不,旧行不会随时间改变。 - Alex Gordon
你需要为所有行进行计算/下载图表,还是仅针对日志中的新条目?此外,这些图表会随时间改变吗? - Cervo
你的计算是密集的运算(大量浮点数/模拟/模型评分),还是简单的求和/计数/趋势/分组? - mcpeterson
我正在对数据集中的每一行取对数,然后进行一些简单的操作,比如乘法。 - Alex Gordon
5个回答

4
只有在以下情况下,我才会将数据放入关系数据库中:
1. 数据实际上是关系型的,并通过规范化来表达它可以帮助缩小数据集的大小。 2. 您可以利用触发器和存储过程来卸载一些Python代码正在执行的计算任务。 3. 您可以利用查询仅对已更改的数据执行计算,从而减少Python所需执行的工作量。
如果这些条件都不成立,我认为数据库和文件之间并没有太大区别。两者都最终必须存储在文件系统中。
如果Python需要处理所有数据,并且将其加载到内存中意味着加载整个数据集,则数据库和扁平文件之间没有区别。
在内存中存储2GB的数据可能会导致应用程序进行页面交换和抖动。在将问题归咎于文件之前,建议小心并获取一些数据。即使您从数据库中访问数据,也不能解决页面交换问题。
如果您的数据是扁平的,除非“扁平”等于“高度去规范化”,否则我认为使用数据库并没有太大优势。
在进行更改之前,我建议进行一些分析以查看CPU和内存的消耗情况。目前,您正在猜测根本原因。最好获取一些数据,以便了解时间花费的具体位置。

请纠正我,但例如一个需要你排序的巨大文件上使用数据库会更好,对吗? - Alex Gordon
答案取决于文件和模式。您是正确的,数据库擅长排序,但还有其他考虑因素:索引、JOIN数量等。 - duffymo
它是平面的。没有关系数据。 - Alex Gordon
问题在于我不确定他在做什么,甚至不知道他是否需要整个2-4 GB的文件,或者这只是他期望文件增长到的总大小,他只需要最后几MB或几百MB进行处理... - Cervo
一个数据库不会比一个进行快速排序的C程序更快。数据库被设计用来处理约束、数据类型检查,并且通常会使用临时文件,因为它必须服务于多个请求。一个具有紧密数组的C程序可能会优于数据库进行排序。此外,一旦排序完成,使用C进行搜索可能会更快,因为不需要索引查找/锁定,而且所有内容都已经在RAM中了。更重要的问题是计算的性质。对于纯粹的加速,我不会使用数据库。但是,如果需要更好的数据组织和后续报告,则可以使用数据库。 - Cervo
显示剩余2条评论

4

如果每次进行"微调"时都需要遍历所有行,假设实际的"微调"是在占用您的循环周期,那么这并不会有太大的区别。

也许您可以以某种方式存储计算结果,然后数据库可能会很好用。此外,数据库具有确保数据完整性等方法,因此数据库通常是存储大量数据的绝佳场所(当然啦! ;)).


+1 表示“存储计算结果”。我要指出的是,如果您选择在计算结束时将它们添加到文件中,那么也可以使用文件进行存储,所以这没有区别。 - duffymo
是的 :) 当然,数据库最终不过是一些花哨的算法和“文件”。因此,如果您愿意,可以使用Python重新发明数据库(这实际上听起来很有趣...)。 - André Laszlo
1
通常,数据库都是用编译语言编写的。对于排序编译语言而言,Python则相差了几个数量级。此外,有时数据库可以自动并行处理处理器/磁盘上的内容。但是与此同时,数据库大多仅仅是存储数据的另一种方式。除非您计划利用其提供的某些功能来加快速度,否则它不会神奇地使事情变得更快。在每条记录的基础上,即使是脚本语言也能打败SQL游标。 - Cervo

4
我不确定你正在做什么,但是数据库只会改变数据的存储方式。实际上,由于大多数合理的数据库可能对列施加限制并进行额外的处理以进行检查,因此这可能需要更长的时间。在许多情况下,将整个文件本地化,进行计算会比查询并将其写回数据库更有效(受磁盘速度、网络和数据库争用等因素影响)。但在某些情况下,数据库可能会加快速度,特别是因为如果您进行索引,很容易获得子集数据。
无论如何,你提到了日志,所以在你使用数据库之前,我有以下想法供你参考。我不确定你是否必须一直浏览自始至终的每个日志以下载图表,并且你期望它增长到2 GB,或者最终你期望每天/每周有2GB的流量。
  1. 存档 —— 您可以将旧日志进行存档,比如每隔几个月。将生产日志复制到归档位置并清除实时日志。这将使文件大小保持合理。如果您浪费时间访问文件以查找所需的小块内容,则此方法将解决您的问题。

  2. 您可能需要考虑转换为Java或C语言。特别是在循环和计算方面,您可能会看到30倍或更多的加速。这可能会立即缩短时间。但随着数据逐渐增加,有一天它也会变慢。如果没有数据量的限制,即使是世界上最伟大的程序员手动优化汇编代码也会变得太慢。但它可能会给您10倍的时间……

  3. 您还可以考虑找出瓶颈(是磁盘访问还是CPU时间),并根据此确定以并行方式执行此任务的方案。如果是处理,可以考虑多线程(最终是多台计算机),如果是磁盘访问,请考虑将文件分割成多个部分并分配给多台计算机……这真的取决于您的情况。但我认为存档可能会消除此处的需要。

  4. 正如建议的那样,如果您一遍又一遍地进行相同的计算,请将它们存储起来。无论您使用数据库还是文件,这都将大大加速。

  5. 如果您正在下载内容并且这是瓶颈,请考虑使用if modified请求进行条件获取。然后仅下载更改的项目。如果您只是处理新的图表,则忽略此建议。

  6. 如果您正在顺序读取巨大的日志文件,并逐行查找特定位置,则只需创建另一个文件来存储您上次处理的文件位置,然后每次运行时执行搜索。

  7. 在整个数据库之前,您可能需要考虑SQLite。

  8. 最后,“几年”在程序员时间中似乎很长。即使只有2年,很多事情都会发生变化。也许您的部门/分部将被裁员。也许您和您的老板已经离职了。也许该系统将被其他东西替换。也许不再需要您正在做的事情。如果只有6个月,我会说解决它。但对于几年,在大多数情况下,我会说现在使用您拥有的解决方案,一旦它变得太慢,再考虑其他方法。您可以在代码中发表评论,包括您对此问题的想法和给老板的电子邮件,以便他也知道。但只要它能工作并且将继续工作一段合理的时间,我会认为它已经“完成”了。无论您选择哪种解决方案,如果数据不断增长,您都需要重新考虑它。添加更多的机器、更多的磁盘空间、新的算法/系统/开发。解决“几年”的问题可能非常好。


Java或C比Python快30倍?!?!? - Alex Gordon
@Paul Nathan - 哇,实际上我在某些C和Python之间的测试中看到了30倍的速度提升(虽然不是最近)。C和Python之间只有10倍的差距,这对于Python来说是一个巨大的改进... - Cervo
实际上,在某些情况下,Python 有时会输给 C 高达 85 倍。无论如何,我在使用 30 的时候是比较保守的,但是 Python 通常比 C 慢一个数量级,有时甚至针对特定基准测试慢 100 倍。Java 和 C 接近,在大多数基准测试中相差 1x-5x。但是,仍然可以通过 5x 在一天内完成一周的工作量。通常,像 1 或 5 这样的常数因素并不重要,但是对于大型数据集,每一点都有所帮助... - Cervo
@Cervo:看了一下我链接里的基准测试,它...嗯...从10倍开始,然后就越来越糟糕了。我应该提高一下我的高级 C++ 技能... - Paul Nathan
显示剩余2条评论

2

在处理大型数据集时,我总是使用数据库。

数据库为我提供了一些免费的东西; 也就是说,我不需要编写代码。

  • 搜索
  • 排序
  • 索引
  • 独立于语言的连接

像SQLite这样的东西可能适合你。

此外,你应该调查一下“nosql”数据库;听起来你的问题可能很适合其中之一。


此外,数据库会给你一些你没有要求的东西,比如并发、锁定、约束等等...大多数情况下,你需要这些,但从文本文件中读取时,它会添加一些你不需要的额外内容。一定要探索优化文本文件,然后使用NOSQL和SQLLite解决方案。最后再考虑使用数据库。虽然我认为仅仅为了加速,使用数据库是没有帮助的。你可能可以自己更快地进行排序。4GB已经可以放入内存中,因此快速排序(甚至两个快速排序和一个合并)可能会比数据库排序更快。 - Cervo
假设您没有使用Python来进行此类排序,那么错误的假设。对于大量的记录,即使是数据库排序可能比Python更快,因为编译有其优势... - Cervo
NoSQL是一类数据库管理系统,通常它们没有关系约束,而且往往也没有ACID属性。 - Paul Nathan
@Cervo: "NoSQL" == "Not Only SQL". 看一下CouchDB,Voldemort,Neo4J,Hadoop,BigTable等数据库。http://nosql-database.org/ - duffymo
我在考虑一些更简单的NoSQL解决方案。但通常任何数据库都会带有整个事务处理/锁定负担和数据完整性检查。并非所有NoSQL解决方案都具备这些功能。一些解决方案比其他解决方案更复杂,用于处理事务的不同方面。我想得更多的是像BDB这样超级简单的解决方案(好吧,我认为那不适用于这个问题),而不是像BigTable或Cassandra这样的解决方案。 - Cervo

1

在2GB的情况下,您可能会开始遇到速度问题。我使用模型模拟,需要调用数百个csv文件,每次循环大约需要一个小时,或每个循环约20分钟。

这是个人喜好的问题,但我会选择类似PostGreSql这样的东西,因为它将Python的速度与SQL驱动关系数据库的容量集成在一起。几年前,当我的Access数据库自己损坏并每天崩溃时,我也遇到了同样的问题。当时我可以选择MySQL或PostGres,最终我选择了后者,因为它更加友好于Python。并不是说MySQL不能与Python一起使用,因为它确实可以,这就是为什么我说这是个人喜好的原因。

希望这对您的决策有所帮助!


非常感谢,这非常有帮助。您能举个例子说明为什么Postgres更好吗? - Alex Gordon
我不会说Postgres比MySQL或甚至Oracle更好。对我来说,这是成本的问题。Postgres是开源的,而我的数据库是非商业性质的,因此我希望保持尽可能透明和灵活。我也喜欢PostgreSQL的界面,从可用性的角度来看,它符合我的学习曲线。 - myClone
我认为Duffymo的解释已经涵盖了这个问题。关系型数据库非常强大,可以处理你要求Python完成的许多任务。然而,如果你只是对存储和引用感兴趣,并且几乎不需要查询/计算,那么我的假设是你最终会执行计算并添加/更改数据,这就是为什么我建议使用关系型数据库管理系统的原因。 - myClone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接