簡體   English   中英

Python DBM 真的很快嗎?

[英]Is Python DBM really fast?

我在想 Python 的原生 DBM 應該比東京內閣、MongoDB 等 NOSQL 數據庫快得多(因為 Python DBM 的功能和選項較少;即更簡單的系統)。 我用一個非常簡單的寫/讀示例進行了測試

#!/usr/bin/python
import time
t = time.time()
import anydbm
count = 0
while (count < 1000):
 db = anydbm.open("dbm2", "c")
 db["1"] = "something"
 db.close()
 db = anydbm.open("dbm", "r")
 print "dict['Name']: ", db['1'];
 print "%.3f" % (time.time()-t)
 db.close()
 count = count + 1

讀/寫:1.3s 讀:0.3s 寫:1.0s

MongoDb 的這些值至少要快 5 倍。 真的是Python DBM的性能嗎?

Python 沒有內置的 DBM 實現。 它的 DBM 功能基於廣泛的 DBM 風格的第三方庫,如 AnyDBM、Berkeley DBM 和 GNU DBM。

Python 的字典實現對於鍵值存儲來說非常快,但不是持久的。 如果您需要高性能運行時鍵值查找,您可能會找到一個更好的字典 - 您可以使用 cpickle 或 shelve 之類的東西來管理持久性。 如果啟動時間對您很重要(如果您正在修改數據、終止)——比運行時訪問速度更重要——那么像 DBM 這樣的東西會更好。

在您的評估中,作為主循環的一部分,您包括了 dbm open 調用和數組查找。 在查找之前打開 DBM 來存儲一個值並關閉並重新打開是一個非常不切實際的用例,並且您會看到以這種方式管理持久性數據存儲時典型的緩慢性能(它是相當低效)。

根據您的要求,如果您需要快速查找並且不太關心啟動時間,DBM 可能是一個解決方案 - 但為了對其進行基准測試,只包括循環中的寫入和讀取! 像下面這樣的東西可能是合適的:

import anydbm
from random import random
import time

# open DBM outside of the timed loops
db = anydbm.open("dbm2", "c")

max_records = 100000

# only time read and write operations
t = time.time()

# create some records
for i in range(max_records):
  db[str(i)] = 'x'

# do a some random reads
for i in range(max_records):
  x = db[str(int(random() * max_records))]

time_taken = time.time() - t
print "Took %0.3f seconds, %0.5f microseconds / record" % (time_taken, (time_taken * 1000000) / max_records)

db.close()

嵌入式密鑰庫在 python3 中足夠快。 以原生字典為基准,說

for k in random.choices(auList,k=100000000):
    a=auDict[k]
CPU times: user 1min 6s, sys: 1.07 s, total: **1min 7s**

GDBM 對此並沒有壞處

%%time
with db.open("AuDictJson.gdbm",'r') as d:
    for k in random.choices(auList,k=100000000):   
        a=d[str(k)]   
CPU times: user 2min 44s, sys: 1.31 s, total: **2min 45s**

即使是專業的預編譯表,作為 json 序列化列表的 keyvy,也可以做幾乎相同的事情。

%%time
d = keyvi.Dictionary("AuDictJson.keyvi")
for k in random.choices(auList,k=100000000):   
    a=d[str(k)].GetValue()
CPU times: user 7min 45s, sys: 1.48 s, total: 7min 47s

一般來說,嵌入式數據庫,特別是當它是只讀和單用戶時,應該總是會贏得外部數據庫,因為訪問資源的套接字和信號量的開銷。 另一方面,如果你的程序是一個已經有一些外部 I/O 瓶頸的服務——比如你正在編寫一個 web 服務——,訪問資源的開銷可能並不重要。

也就是說,如果它們提供額外的服務,您可以看到使用外部數據庫的一些優勢。 對於 Redis,請考慮集合的並集。

%%time
for j in range(1000):
    k=r.sunion(('s'+str(k) for k in random.choices(auList,k=10000)))  
CPU times: user 2min 24s, sys: 758 ms, total: 2min 25s

與 gbm 相同的任務處於相同的數量級。 盡管 redis 仍然慢了 5 倍,但它不會慢到丟棄它

%%time 
with db.open("AuDictPSV.gdbm",'r') as d:
    for j in range(1000):
        a=set()
        for k in random.choices(auList,k=10000):
            a.update(d[str(k)].split(b'|'))
CPU times: user 33.6 s, sys: 3.5 ms, total: 33.6 s

通過在這種情況下使用 redis,您可以獲得數據庫的全部功能,而不僅僅是簡單的數據存儲。 當然,由於有很多客戶端使其飽和,或者有很多單次獲取,與嵌入式資源相比,它的性能會很差。

至於 gdbm 的競爭,Charles Leifer 2014 年的一項基准測試表明,它可以在讀取方面超過京都內閣,但在寫入方面仍然並列,並且可以將 LevelDB 和 RocksDB 視為高級替代品。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM