25

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

  1. 腌制字典对象:不确定这是否是我的问题的最佳解决方案
  2. NoSQL 类型 dbases :理想情况下,希望对第三方的依赖最小的东西加上键值就是简单的数字。如果你觉得这仍然是最好的选择,我也想听听。也许它会说服我。

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

谢谢!-阿比

4

6 回答 6

20

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

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

于 2012-08-06T23:15:43.637 回答
13

原则上,搁置模块完全符合您的要求。它提供了一个由数据库文件支持的持久字典。键必须是字符串,但 shelve 会处理酸洗/取消酸洗值。db 文件的类型可以变化,但可以是Berkeley DB哈希,这是一个优秀的轻量级键值数据库。

您的数据量听起来很大,因此您必须进行一些测试,但搁置/BDB 可能取决于它。

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

于 2012-08-07T00:01:41.040 回答
13

没有人提到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.

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

干杯

蒂姆

于 2012-08-07T01:05:41.303 回答
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. @antrirez
于 2012-08-06T23:20:49.487 回答
4

我认为你不应该尝试腌制的字典。我很确定 Python 每次都会吃掉整个东西,这意味着你的程序等待 I/O 的时间可能比必要的要长。

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

具有非常大的数据库文件的 sqlite 的性能特点是什么?

于 2012-08-06T23:17:05.053 回答
3

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

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

于 2016-05-11T09:17:38.987 回答