2012-08-06 35 views
19

我有一個4億行獨特的鍵值信息,我希望可以在腳本中快速查找。我想知道這將是一個什麼樣的光滑方式。我確實考慮了以下內容,但不確定是否有磁盤映射字典的方法,並且除了在字典創建期間不使用大量內存。*大型* python詞典與持久性存儲快速查找

  1. 醃Dictionary對象:不知道這是我的問題的最佳解決方案
  2. 的NoSQL型dbases:非常想要的東西,這對第三方的東西加上鍵值最小的依賴是簡單的數字。如果你覺得這仍然是最好的選擇,我也想聽到。可能會說服我。

請讓我知道,如果有什麼不清楚。

謝謝! -Abhi

+15

持久性=數據庫的大字典。 – 2012-08-06 23:13:29

+0

我聽說couch-db對於這類事情非常有用(但從來不必使用它...) – 2012-08-06 23:25:11

回答

16

如果你想堅持一個大的字典,你基本上看着一個數據庫。

Python內置支持sqlite3,它爲您提供了一個簡單的數據庫解決方案,由磁盤上的文件支持。

+0

我需要找到其他SO問題的鏈接,這個問題使用數據庫來處理大量的DNA序列。 – 2012-08-07 04:31:33

+0

好吧,這將有所幫助 – Abhi 2012-08-07 07:01:07

+1

實現了這一點,併爲我們需要的速度正常工作:) – Abhi 2012-08-08 17:39:43

4

我不認爲你應該嘗試醃字典。我非常肯定,Python每次都會啜泣,這意味着你的程序將等待I/O的時間超過可能需要的時間。

這是發明數據庫的問題。你在想「NoSQL」,但是SQL數據庫也可以。你應該可以使用SQLite來做到這一點;我從來沒有創建過一個很大的SQLite數據庫,但根據對SQLite限制的討論,4億條應該沒問題。

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

+0

那麼SQL可以工作,但也可能是一種矯枉過正。 – LtWorf 2014-09-09 16:21:09

+1

SQLite並非真正的「矯枉過正」。有這麼多項目使用它的原因。 – steveha 2014-09-10 02:38:34

5

毫無疑問,(在我看來),如果你想這樣堅持,那麼Redis是一個很好的選擇。

  1. 安裝Redis的服務器
  2. 開始Redis的服務器
  3. 安裝Redis的蟒蛇pacakge(PIP安裝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
+0

只是想知道你是否玩過其他鍵值存儲分貝,並有任何關於它們的說法..謝謝 – Abhi 2012-08-06 23:26:25

11

原則上shelve模塊不正是你想要什麼。它提供了一個由數據庫文件支持的持久字典。鑰匙必須是字符串,但擱置將會照顧酸洗/取消價值。 db文件的類型可以有所不同,但它可以是一個Berkeley DB散列,它是一個優秀的輕量級鍵值數據庫。

您的數據大小聽起來很大,因此您必須進行一些測試,但擱置/ BDB可能取決於它。

注意:bsddb模塊已被棄用。將來可能擱置不會支持BDB哈希。

7

沒有人提到過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() 

之前任何的更奇特的形式我會嘗試這一點,並使用擱置/泡菜會拉一切到內存上加載。

乾杯

+1

在早期版本的Python中,這是'anydbm'模塊。 – 2014-05-15 14:50:34

2

我個人使用LMDB及其python binding幾百萬條記錄DB。 即使數據庫大於RAM,速度也非常快。 它嵌入進程中,因此不需要服務器。 依賴項使用pip進行管理。

唯一的缺點是您必須指定數據庫的最大大小。 LMDB將會映射這種大小的文件。如果太小,插入新數據將會引發錯誤。大,你創建稀疏文件。