*大型* python 字典,具有持久性存储,可快速查找

问题描述 投票:0回答:6

我有 4 亿行唯一的键值信息,我希望可以在脚本中快速查找这些信息。我想知道什么是一个巧妙的方法来做到这一点。我确实考虑了以下内容,但不确定是否有一种方法可以磁盘映射字典并且除了在字典创建期间之外不使用大量内存。

  1. pickled 字典对象:不确定这是否是我的问题的最佳解决方案
  2. NoSQL 类型数据库:理想情况下希望对第三方的依赖程度最小,并且键值只是数字。如果您认为这仍然是最佳选择,我也想听听。也许它会说服我。

如果有任何不清楚的地方请告诉我。

谢谢! -阿比

python persistence object-persistence
6个回答
20
投票

如果你想持久化一个大字典,你基本上就是在查看数据库。

Python 内置了对 sqlite3 的支持,它为您提供了一个由磁盘上的文件支持的简单数据库解决方案。


14
投票

没有人提到dbm。它像文件一样打开,行为像字典,并且位于标准发行版中。

来自文档https://docs.python.org/3/library/dbm.html

import dbm

# Open database, creating it if necessary.
with dbm.open('cache', 'c') as db:

    # Record some values
    db[b'hello'] = b'there'
    db['www.python.org'] = 'Python Website'
    db['www.cnn.com'] = 'Cable News Network'

    # Note that the keys are considered bytes now.
    assert db[b'www.python.org'] == b'Python Website'
    # Notice how the value is now in bytes.
    assert db['www.cnn.com'] == b'Cable News Network'

    # Often-used methods of the dict interface work too.
    print(db.get('python.org', b'not present'))

    # Storing a non-string key or value will raise an exception (most
    # likely a TypeError).
    db['www.yahoo.com'] = 4

# db is automatically closed when leaving the with statement.

我会在任何更奇特的形式之前尝试这个,并且使用 shelve/pickle 会在加载时将所有内容拉入内存。

干杯

蒂姆


13
投票

原则上,shelve模块完全可以满足您的需求。它提供由数据库文件支持的持久字典。键必须是字符串,但搁置将处理酸洗/取消酸洗值。数据库文件的类型可以有所不同,但它可以是 Berkeley DB 哈希,这是一个出色的轻量级键值数据库。

您的数据量听起来很大,因此您必须进行一些测试,但 shelve/BDB 可能足以胜任。

注意:bsddb模块已被弃用。未来可能搁置将不支持 BDB 哈希。


5
投票

毫无疑问(在我看来),如果你希望这种情况持续下去,那么 Redis 是一个不错的选择。

  1. 安装redis服务器
  2. 启动redis服务器
  3. 安装redis python pacakge(pip install redis)
  4. 利润。

import redis

ds = redis.Redis(host="localhost", port=6379)

with open("your_text_file.txt") as fh:
    for line in fh:
        line = line.strip()
        k, _, v = line.partition("=")
        ds.set(k, v)

上面假设文件的值如下:

key1=value1
key2=value2
etc=etc

根据您的需要修改插入脚本。


import redis
ds = redis.Redis(host="localhost", port=6379)

# Do your code that needs to do look ups of keys:
for mykey in special_key_list:
    val = ds.get(mykey)

为什么我喜欢Redis。

  1. 可配置的持久性选项
  2. 速度极快
  3. 提供的不仅仅是键/值对(其他数据类型)
  4. @anttrirez

4
投票

我认为你不应该尝试腌菜。我非常确定 Python 每次都会吞掉整个内容,这意味着您的程序等待 I/O 的时间将超过可能需要的时间。

数据库就是为了解决这类问题而发明的。您正在考虑“NoSQL”,但 SQL 数据库也可以工作。您应该能够使用 SQLite 来实现此目的;我从来没有制作过这么大的 SQLite 数据库,但根据 SQLite 限制的讨论,4 亿个条目应该没问题。

对于非常大的数据库文件,sqlite 的性能特点是什么?


3
投票

我个人使用 LMDB 及其 python 绑定 来存储数百万条记录的数据库。 即使对于大于 RAM 的数据库,它也非常快。 它嵌入在流程中,因此不需要服务器。 使用 pip 管理依赖关系。

唯一的缺点是您必须指定数据库的最大大小。 LMDB 将映射此大小的文件。如果太小,插入新数据将引发错误。如果太大,您将创建稀疏文件。

© www.soinside.com 2019 - 2024. All rights reserved.