2010-08-19 3 views
13

저는 파이썬을 사용하여 테이블을 저장하고 있습니다.Shelve가 큰 사전의 경우 너무 느립니다. 성능을 향상 시키려면 어떻게해야합니까?

본질적으로 숫자에 사전 문자열로 테이블을 저장합니다. 그리고 전체가 나는 시스템이 내가하지 않으면 불안정한 경향이 발견 나는 Truewriteback를 사용

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

선반에 저장됩니다.

계산 후 시스템은 데이터베이스를 닫고 다시 저장해야합니다. 이제 데이터베이스 (테이블)는 약 540MB이며, 연령대가 오래되었습니다. 테이블이 약 500MB로 증가한 후에 시간이 폭발했습니다. 하지만 훨씬 더 큰 테이블이 필요합니다. 사실 두 가지가 필요합니다.

나는 아마도 잘못된 형태의 영속성을 사용하고있을 것입니다. 성능 향상을 위해 무엇을 할 수 있습니까?

+0

shelve를 사용하여 큰 dicts에서 부적절한 CPU 사용이 발생 했습니까? –

답변

13

string : number 키 - 값 쌍의 큰 사전을 저장하는 경우 MongoDB과 같은 JSON 고유의 저장 솔루션을 제안합니다. Python을위한 훌륭한 API, Pymongo을 가지고 있습니다. MongoDB 자체는 가볍고 믿을 수 없을 정도로 빠르며, json 객체는 기본적으로 파이썬에서 사전이 될 것입니다. 즉, string 키를 오브젝트 ID로 사용할 수 있으므로 압축 된 저장 및 빠른 검색이 가능합니다. 코드는 것이 얼마나 쉬운 예를 들어

은 다음을 참조하십시오

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} 

그냥 사소한 유니 코드에서 다시 변환해야 할 것이다.

+0

고맙습니다. 데이터는 실제로 대칭 테이블 번호 * number -> number이지만 shelve가 문자열을 키로 원했기 때문에 나는 어떻게 든 테이블 문자열 -> 숫자로 작성하는 데 사용되었습니다. 여기서 문자열은 "a_b"와 a 및 b입니다. 숫자와 a

1

얼마나 더 큽니까? 액세스 패턴은 무엇입니까? 어떤 종류의 계산을해야합니까?

어떻게 수행하든 관계없이 메모리에 테이블을 보관할 수 없다면 성능 제한이 있습니다.

SQLAlchemy로 가거나 직접 bsddb과 같은 것을 사용하는 것이 좋습니다. 두 가지 모두 코드의 단순함을 희생합니다. 그러나 SQL을 사용하면 작업 부하에 따라 일부 작업을 데이터베이스 계층으로 오프로드 할 수 있습니다.

+2

이론적 인 알고리즘을 개발 중이므로 지금 사용하고있는 문제는 아마도 몇 기가 바이트의 테이블을 가지고있을 것입니다. 그러나 사람들이 다른 문제 (주로 시스템 생물학에서 생각하고, 크게 생각하고, 증가 시키십시오)를 위해 알고리즘을 사용할 것이므로, 규모를 확장 할 수있는 솔루션을 찾는 것이 중요합니다. 액세스는 임의적이며 각 용어는 몇 번 액세스됩니다. 내가 할 필요가있는 유일한 계산은 값을 얻고 거기에 없으면 값을 계산하고 저장하는 것입니다. 나는 DB가 메모리에 있지 않도록 MySQL을 사용할 것을 고려하고 있었다. 그러나 코드가 복잡해지고 느려질 수 있습니다. 감사. –

9

내 경험에 비추어 볼 때 파이썬과 함께 제공되는 SQLite3을 사용하는 것이 좋습니다. 더 큰 데이터베이스와 핵심 번호에서 잘 작동합니다. 수백만 개의 키와 기가 바이트 데이터는 문제가되지 않습니다. Shelve는 그 시점에서 완전히 낭비됩니다. 또한 별도의 db 프로세스를 사용하는 것이 도움이되지 않는다. 단지 더 많은 컨텍스트 스왑이 필요하다. 내 테스트에서 나는 더 큰 데이터 세트를 로컬에서 처리 할 때 SQLite3을 사용하는 것이 더 좋은 옵션이라는 것을 알았습니다. mongo, mysql 또는 postgresql과 같은 로컬 데이터베이스 엔진을 실행하면 추가 값이 제공되지 않고 느려집니다.

0

귀하의 문제는 writeback=True을 사용하고 있기 때문입니다. documentation는 (강조 광산입니다) 말한다 : 변경 가능한 지속적인-사전 항목이 수정 될 때 때문에 파이썬 의미의

이 선반은 알 수 없다. 기본적으로 수정 된 개체 은 선반에 할당 된 경우에만 기록됩니다 (예 참조). 선택적 쓰기 저장 매개 변수가 True로 설정된 경우 액세스되는 모든 항목은 이며 메모리에도 캐시되고 sync() 및 close()에 다시 기록됩니다. 이 은 영구적 인 사전에서 변경 가능한 항목을 변경하기 위해보다 손쉽게 처리 할 수 ​​있지만 많은 항목이 액세스되는 경우 개의 캐시 메모리를 사용하고 은 모두 접근하므로 닫기 작업을 수행 할 수 있습니다. 항목은 다시으로 기록됩니다 (액세스 할 수있는 항목을 변경할 수있는 방법은 이 아니며 실제로 변경된 항목은 ).

writeback=True을 사용하지 않고 데이터를 한 번만 기록하면됩니다 (이후 수정 사항이 손실 될 수 있음에 유의해야합니다).

이것이 올바른 저장 옵션이 아니라고 생각하는 경우 (데이터 구조가 무엇인지 모르는 채로 말하기는 어렵습니다) sqlite3을 제안합니다.이 파일은 python에 통합되어 있으므로 매우 유용합니다. 간단한 키 - 값 저장소보다 다소 복잡합니다.

대안에 대한 다른 답변을 찾아보십시오.

관련 문제