Bạn cũng có thể đang sử dụng công cụ sai cho công việc này. Nếu bạn muốn tồn tại một lượng lớn dữ liệu được lập chỉ mục, tôi khuyên bạn nên sử dụng cơ sở dữ liệu trên đĩa SQLite (hoặc, tất nhiên, chỉ là một cơ sở dữ liệu bình thường) với một ORM như SQLObject hoặc SQL Alchemy.
Đây sẽ chăm sóc trong những điều trần tục như khả năng tương thích, tối ưu hóa định dạng cho mục đích, chứ không phải giữ tất cả dữ liệu trong bộ nhớ cùng một lúc để bạn chạy ra khỏi bộ nhớ ...
Added: Bởi vì tôi là Tuy nhiên, chủ yếu là vì tôi là một người tốt, đây là bản demo xuất hiện để làm những gì bạn cần (nó sẽ tạo một tệp SQLite trong thư mục hiện tại của bạn và xóa nó nếu một tệp với tên đã tồn tại, vì vậy hãy đặt nó ở đâu đó trống trước):
import sqlobject
from sqlobject import SQLObject, UnicodeCol, ForeignKey, IntCol, SQLMultipleJoin
import os
DB_NAME = "mydb"
ENCODING = "utf8"
class Document(SQLObject):
dbName = UnicodeCol(dbEncoding=ENCODING)
class Location(SQLObject):
""" Location of each individual occurrence of a word within a document.
"""
dbWord = UnicodeCol(dbEncoding=ENCODING)
dbDocument = ForeignKey('Document')
dbLocation = IntCol()
TEST_DATA = {
'one' : {
'doc1' : [1,2,10],
'doc3' : [6],
},
'two' : {
'doc1' : [2, 13],
'doc2' : [5,6,7],
},
'three' : {
'doc3' : [1],
},
}
if __name__ == "__main__":
db_filename = os.path.abspath(DB_NAME)
if os.path.exists(db_filename):
os.unlink(db_filename)
connection = sqlobject.connectionForURI("sqlite:%s" % (db_filename))
sqlobject.sqlhub.processConnection = connection
# Create the tables
Document.createTable()
Location.createTable()
# Import the dict data:
for word, locs in TEST_DATA.items():
for doc, indices in locs.items():
sql_doc = Document(dbName=doc)
for index in indices:
Location(dbWord=word, dbDocument=sql_doc, dbLocation=index)
# Let's check out the data... where can we find 'two'?
locs_for_two = Location.selectBy(dbWord = 'two')
# Or...
# locs_for_two = Location.select(Location.q.dbWord == 'two')
print "Word 'two' found at..."
for loc in locs_for_two:
print "Found: %s, p%s" % (loc.dbDocument.dbName, loc.dbLocation)
# What documents have 'one' in them?
docs_with_one = Location.selectBy(dbWord = 'one').throughTo.dbDocument
print
print "Word 'one' found in documents..."
for doc in docs_with_one:
print "Found: %s" % doc.dbName
Đây là chứng nhận không phải là cách duy nhất (hoặc nhất thiết là cách tốt nhất) để làm điều này. Việc các bảng Tài liệu hoặc Word có phải là các bảng riêng biệt khỏi bảng Vị trí hay không phụ thuộc vào dữ liệu của bạn và cách sử dụng thông thường. Trong trường hợp của bạn, bảng "Word" có thể là một bảng riêng biệt với một số cài đặt bổ sung để lập chỉ mục và tính duy nhất.
Làm việc như một sự quyến rũ. Sửa chữa cực kỳ đơn giản - về cơ bản chỉ thay đổi "dưa" để "soái" và đã được thực hiện. Tôi đã không nhận ra cPickle thực hiện chu kỳ phát hiện. Bằng cách sử dụng marshal thay vào đó, ghi vào đĩa mất một vài giây như trái ngược với 20 phút, và giảm tiêu thụ bộ nhớ từ 30% và giảm xuống gần 0%. Cảm ơn! –
Giải pháp đơn giản cộng với lời giải thích ngắn gọn, tuyệt vời 100%. – mitchus
Điều cần biết, cảm ơn @gnibbler! –