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

时间:2012-08-06 23:11:38

标签: python persistence object-persistence

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

  1. 腌制字典对象:不确定这是否是我问题的最佳解决方案
  2. NoSQL类型dbases:理想情况下需要对第三方内容具有最小依赖性的东西加上键值只是数字。如果你觉得这仍然是最好的选择,我也想听听。可能会说服我。
  3. 如果有任何不清楚的地方,请告诉我。

    谢谢! -Abhi

6 个答案:

答案 0 :(得分:17)

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

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

答案 1 :(得分:12)

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

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

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

答案 2 :(得分:10)

没有人提到过dbm。它像文件一样打开,表现得像字典,属于标准发行版。

来自文档http://docs.python.org/release/3.0.1/library/dbm.html

import dbm

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

# 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'

# Loop through contents.  Other dictionary methods
# such as .keys(), .values() also work.
for k, v in db.iteritems():
print(k, '\t', v)

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

# Close when done.
db.close()

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

干杯

答案 3 :(得分:5)

毫无疑问(在我看来),如果你想要坚持下去,那么Redis是一个不错的选择。

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

  5. 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

答案 4 :(得分:4)

我认为你不应该尝试腌制的字典。我很确定Python会在每次都沾染整个东西,这意味着你的程序会等待I / O超过可能的时间。

这就是发明数据库的问题。您正在考虑“NoSQL”,但SQL数据库也可以工作。你应该能够使用SQLite;我从未创建过大的SQLite数据库,但根据SQLite限制的讨论,4亿条目应该没问题。

What are the performance characteristics of sqlite with very large database files?

答案 5 :(得分:2)

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

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