在python中存储大量数据

时间:2011-03-10 18:43:01

标签: python

也许我开始对我的问题做一个小介绍。我正在写一个python程序,它将用于不同物理模拟的后处理。每次模拟都可以创建高达100 GB的输出。我处理不同时间步骤的不同信息(如位置,字段和密度......)。我希望能够同时访问所有这些数据,这是不可能的,因为我的系统上没有足够的内存。通常我使用读取文件,然后执行一些操作并清除内存。然后我读取其他数据并执行一些操作并清除内存。

现在我的问题。如果我这样做,那么我花了很多时间不止一次读取数据。这需要花费很多时间。我想只读一次并存储它以方便访问。您是否知道存储大量数据的方法,这些数据非常快或者不需要大量空间。

我刚刚创建了一个方法,比普通的open-read快了大约十倍。但我使用cat(linux命令)。这是一个非常脏的方法,我想把它从我的脚本中删除。

是否可以使用数据库来存储此数据并使数据比正常读取更快? (抱歉这个问题,但我不是计算机科学家,我在数据库背后没有很多知识)。

修改

我的猫代码看起来像这样 - 只是一个例子:

out = string.split(os.popen("cat "+base+"phs/phs01_00023_"+time).read())
# and if I want to have this data as arrays then I normally use and reshape (if I
# need it)
out = array(out)
out = reshape(out)

通常我会使用numpy方法numpy.loadtxt,它需要与正常阅读相同的时间。:

f = open('filename')
f.read()
...

我认为loadtxt只是使用常规方法和一些额外的代码行。

我知道有更好的方法可以读出数据。但我发现的一切都很慢。我现在尝试mmap,希望我会有更好的表现。

3 个答案:

答案 0 :(得分:7)

我会尝试使用HDF5。有两种常用的Python接口,h5pyPyTables。虽然后者似乎更为普遍,但我更喜欢前者。

答案 1 :(得分:7)

如果您使用的是64位操作系统,则可以使用mmap模块将整个文件映射到内存空间。然后,由于操作系统负责管理您的访问模式,因此可以更快地完成读取数据的随机位。请注意,实际上您不需要100 GB的RAM才能工作,因为操作系统将在虚拟内存中管理它。

我在64位FreeBSD 8上使用30 GB文件(Wikipedia XML文章转储)完成了这项工作,效果非常好。

答案 2 :(得分:0)

如果您正在使用大型数据集,Python可能不是您最好的选择。如果你想使用像MySQL或Postgres这样的数据库,你应该试试SQLAlchemy。使用小型Python对象可以很容易地处理潜在的大型数据集。例如,如果您使用这样的定义:

from datetime import datetime
from sqlalchemy import Column, DateTime, Enum, ForeignKey, Integer, \
    MetaData, PickleType, String, Text, Table, LargeBinary
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import column_property, deferred, object_session, \
    relation, backref

SqlaBaseClass = declarative_base()

class MyDataObject(SqlaBaseClass):
  __tablename__ = 'datarows'
  eltid         = Column(Integer, primary_key=True)
  name          = Column(String(50, convert_unicode=True), nullable=False, unique=True, index=True)
  created       = Column(DateTime)
  updated       = Column(DateTime, default=datetime.today)

  mylargecontent = deferred(Column(LargeBinary))

  def __init__(self, name):
      self.name    = name
      self.created = datetime.today()

  def __repr__(self):
      return "<MyDataObject name='%s'>" %(self.name,)

然后,您可以使用小型数据对象轻松访问所有行:

# set up database connection; open dbsession; ... 

for elt in dbsession.query(MyDataObject).all():
    print elt.eltid # does not access mylargecontent

    if (something(elt)):
        process(elt.mylargecontent) # now large binary is pulled from db server
                                    # on demand

我想重点是:您可以根据需要为数据添加任意数量的字段,根据需要添加索引以加快搜索速度。最重要的是,当您使用MyDataObject时,您可以制作潜在的大字段deferred,以便只在您需要时加载它们。