2010-08-19 13 views
13

Tôi đang lưu trữ một bảng bằng cách sử dụng python và tôi cần sự kiên trì.Giá sách quá chậm đối với các từ điển lớn, tôi có thể làm gì để cải thiện hiệu suất?

Về cơ bản, tôi lưu trữ bảng dưới dạng chuỗi từ điển thành số. Và toàn bộ được lưu trữ với xiên

self.DB=shelve.open("%s%sMoleculeLibrary.shelve"%(directory,os.sep),writeback=True) 

tôi sử dụng writeback-True như tôi thấy hệ thống có xu hướng không ổn định nếu tôi không làm.

Sau khi tính toán, hệ thống cần đóng cơ sở dữ liệu và lưu trữ lại. Bây giờ cơ sở dữ liệu (bảng) là khoảng 540MB, và nó đang mất lứa tuổi. Thời gian bùng nổ sau khi bảng tăng lên khoảng 500MB. Nhưng tôi cần một cái bàn lớn hơn nhiều. Trong thực tế, tôi cần hai trong số họ.

Tôi có thể đang sử dụng sai hình thức kiên trì. Tôi có thể làm gì để cải thiện hiệu suất?

+0

Bạn đã gặp phải việc sử dụng CPU không đầy đủ với các dicts lớn sử dụng giá đỡ chưa? –

Trả lời

13

Để lưu trữ một từ điển lớn gồm string : number cặp khóa-giá trị, tôi muốn đề xuất giải pháp lưu trữ gốc JSON chẳng hạn như MongoDB. Nó có một API tuyệt vời cho Python, Pymongo. MongoDB chính nó là nhẹ và cực nhanh, và các đối tượng json sẽ tự nhiên là từ điển trong Python. Điều này có nghĩa là bạn có thể sử dụng khóa string làm ID đối tượng, cho phép lưu trữ được nén và tra cứu nhanh.

Là một ví dụ về cách dễ dàng mã sẽ, thấy như sau:

d = {'string1' : 1, 'string2' : 2, 'string3' : 3} 
from pymongo import Connection 
conn = Connection() 
db = conn['example-database'] 
collection = db['example-collection'] 
for string, num in d.items(): 
    collection.save({'_id' : string, 'value' : num}) 
# testing 
newD = {} 
for obj in collection.find(): 
    newD[obj['_id']] = obj['value'] 
print newD 
# output is: {u'string2': 2, u'string3': 3, u'string1': 1} 

Bạn chỉ muốn phải chuyển đổi lại từ unicode, mà là tầm thường.

+0

Cảm ơn bạn. Dữ liệu thực sự là một số bảng đối xứng * số -> số, nhưng vì giá treo muốn các chuỗi như là chìa khóa tôi đã bằng cách nào đó tạo ra nó như một chuỗi bảng -> số, trong đó chuỗi là "a_b" với a và b số và một

1

Lớn hơn bao nhiêu? Các mẫu truy cập là gì? Những loại tính toán nào bạn cần làm trên đó?

Hãy nhớ rằng bạn sẽ có một số giới hạn hiệu suất nếu bạn không thể giữ bảng trong bộ nhớ bất kể bạn làm như thế nào.

Bạn có thể muốn xem xét đến SQLAlchemy, hoặc trực tiếp sử dụng một cái gì đó như bsddb, nhưng cả hai đều sẽ hy sinh sự đơn giản của mã. Tuy nhiên, với SQL bạn có thể giảm tải một số công việc cho tầng cơ sở dữ liệu tùy thuộc vào khối lượng công việc.

+2

Tôi đang phát triển một thuật toán lý thuyết, do đó, vấn đề tôi đang sử dụng hiện nay có thể là bảng của một vài giga. Nhưng khi mọi người sẽ sử dụng thuật toán cho các vấn đề khác (chủ yếu trong hệ thống sinh học, suy nghĩ lớn, sau đó tăng) điều quan trọng là tìm một giải pháp có thể mở rộng quy mô. Quyền truy cập là ngẫu nhiên và mỗi lần truy cập sẽ được truy cập vài lần. Tính toán duy nhất tôi cần làm là lấy giá trị, tính giá trị nếu nó không có ở đó và lưu trữ nó. Tôi đã xem xét việc sử dụng MySQL để DB không có trong bộ nhớ. Nhưng nó sẽ làm cho mã phức tạp hơn và chậm hơn. Cảm ơn. –

9

Dựa trên kinh nghiệm của tôi, tôi khuyên bạn nên sử dụng SQLite3, đi kèm với Python. Nó hoạt động tốt với các cơ sở dữ liệu lớn hơn và các số chính. Hàng triệu khóa và gigabyte dữ liệu không phải là vấn đề. Kệ là hoàn toàn lãng phí tại thời điểm đó. Cũng có quá trình db riêng biệt không có lợi, nó chỉ đòi hỏi nhiều hoán đổi ngữ cảnh hơn. Trong các thử nghiệm của tôi, tôi phát hiện ra rằng SQLite3 là tùy chọn ưa thích để sử dụng, khi xử lý các tập dữ liệu lớn hơn cục bộ. Chạy công cụ cơ sở dữ liệu cục bộ như mongo, mysql hoặc postgresql không cung cấp bất kỳ giá trị bổ sung nào và cũng chậm hơn.

0

Tôi nghĩ vấn đề của bạn là do bạn sử dụng writeback=True. Các documentation nói (nhấn mạnh là của tôi):

Bởi vì ngữ nghĩa Python, một kệ không thể biết khi nào một mutable nhập persistent-từ điển được sửa đổi. Theo các đối tượng được sửa đổi mặc định, chỉ được viết khi được gán cho giá (xem Ví dụ).Nếu tham số tùy chọn writeback được đặt thành True, tất cả các mục được truy cập là cũng được lưu vào bộ nhớ cache và được ghi lại trên đồng bộ hóa() và đóng(); có thể làm cho nó dễ dàng hơn để thay đổi các mục có thể thay đổi trong từ điển liên tục, nhưng nếu nhiều mục được truy cập, nó có thể tiêu tốn một lượng lớn bộ nhớ cho bộ nhớ cache và nó có thể làm cho hoạt động gần như rất chậm. các mục được viết lại (không có cách nào để xác định các mục nhập truy cập nào có thể thay đổi được, cũng không phải mục nhập nào là thực sự bị đột biến).

Bạn có thể tránh sử dụng writeback=True và đảm bảo dữ liệu chỉ được viết một lần (bạn phải chú ý rằng các sửa đổi tiếp theo sẽ bị mất).

Nếu bạn tin rằng đây không phải là tùy chọn lưu trữ phù hợp (rất khó để nói mà không biết dữ liệu được cấu trúc như thế nào), tôi đề nghị sqlite3, nó được tích hợp trong python (do đó rất di động) và có hiệu suất rất đẹp. Nó hơi phức tạp hơn một kho khóa-giá trị đơn giản.

Xem câu trả lời khác cho các lựa chọn thay thế.