문제

편집 : 모든 답변에 감사드립니다. 지금까지 최적화를 적용한 후 결과는 다음과 같습니다.

  • 문자 정렬 및 길이 인코딩을 정렬하도록 전환 - 새로운 DB 크기 42m
  • 부울에서 인덱스 삭제 - 새로운 DB 크기 33m

정말 좋은 부분은 이것이 iPhone 코드의 변경이 필요하지 않다는 것입니다.

큰 사전이 SQLite 형식으로 유지 된 iPhone 응용 프로그램이 있습니다 (읽기 만). 현재 매우 큰 DB 파일의 크기를 줄이는 아이디어를 찾고 있습니다.

다음은 Sqlite DB의 항목 수와 결과 크기입니다.

franks-macbook:DictionaryMaker frank$ ls -lh dictionary.db
-rw-r--r--  1 frank  staff    59M  8 Oct 23:08 dictionary.db
franks-macbook:DictionaryMaker frank$ wc -l dictionary.txt
  453154 dictionary.txt

... 항목 당 평균 약 135 바이트.

내 DB 스키마는 다음과 같습니다.

create table words (word text primary key, sowpods boolean, twl boolean, signature text)
create index sowpods_idx on words(sowpods)
create index twl_idx on words(twl)
create index signature_idx on words(signature)

다음은 몇 가지 샘플 데이터입니다.

photoengrave|1|1|10002011000001210101010000
photoengraved|1|1|10012011000001210101010000
photoengraver|1|1|10002011000001210201010000
photoengravers|1|1|10002011000001210211010000
photoengraves|1|1|10002011000001210111010000
photoengraving|1|1|10001021100002210101010000

마지막 필드는 아나그램 검색의 문자 빈도를 나타냅니다 (각 위치는 0..9 범위에 있습니다). 두 부울은 하위 사전을 나타냅니다.

다음과 같은 쿼리를해야합니다.

select signature from words where word = 'foo'
select word from words where signature = '10001021100002210101010000' order by word asc
select word from words where word like 'foo' order by word asc
select word from words where word = 'foo' and (sowpods='1' or twl='1')

내가 가진 아이디어 중 하나는 문자 주파수를보다 효율적으로 인코딩하는 것입니다. 예를 들어 Binary는이를 블로브로 인코딩하는 것입니다 (아마도 많은 0이있는 RLE가 있습니까?). 이를 달성하는 가장 좋은 방법이나 크기를 줄이기위한 다른 아이디어에 대한 아이디어가 있습니까? 나는 루비에 DB를 만들고 대 Objective C로 전화로 읽고 있습니다.

또한 가장 많은 공간을 사용하는 것을 볼 수 있도록 DB에서 통계를 얻는 방법이 있습니까?

도움이 되었습니까?

해결책

서명 필드의 모든 사용 사례는 명확하지 않지만 대신 알파벳 화 된 단어의 단어를 저장하는 것이 유익 할 것 같습니다.

다른 팁

"진공"명령을 입력하여 DB에 여분의 공간이 없는지 확인 했습니까?

SowPods 및 TWL에서 인덱스를 제거하십시오. 아마도 쿼리 시간을 돕지 않으며 확실히 많은 공간을 차지하고 있습니다.

데이터베이스를 사용하여 통계를 얻을 수 있습니다 sqlite3_analyzer ~로부터 sqlite 다운로드 페이지.

완전히 다른 접근법으로, 당신은 블룸 필터 포괄적 인 데이터베이스 대신. 기본적으로 블룸 필터는 다양한 해시 함수로 구성되며 각각은 비트 필드와 관련이 있습니다. 각 법적 단어에 대해 각 해시 함수가 평가되고 해당 비트 필드의 해당 비트가 설정됩니다. 단점은 이론적으로 잘못된 긍정을 얻는 것이 가능하지만, 충분한 해시로 최소화/실질적으로 제거 할 수 있습니다. Plus Side는 큰 공간 절약입니다.

SQLITE의 제작자는 데이터베이스 압축 (및 암호화)을 포함하는 SQLITE 버전을 판매합니다. 이것은 완벽 할 것입니다.

가장 좋은 방법은 압축을 사용하는 것입니다. 불행히도 SQLITE는이 시점에서 기본적으로 지원하지 않는 압축입니다. 운 좋게도 누군가는 시간을내어 발전했습니다 압축 확장 당신이 필요로 할 수있는 것입니다.

그렇지 않으면 데이터를 대부분 압축 형식으로 저장하고 즉시 압축하지 않도록 권장합니다.

As a text field, signature is currently using at least 26 * 8 bytes per entry (208 bytes) but if you were to pack the data into a bitfield, you could probably get away with only 3 bits per letter (reducing your maximum frequency per letter to 7). That would mean you could pack the entire signature in 26 * 3 bits = 78 bits = 10 bytes. Even if you used 4 bits per letter (for a maximum frequency of 15 per letter) you would only use 104 bits (13 bytes).

EDIT: After a bit more thought, I think 4 bits per letter (instead of 3) would be a better idea because it would make the binary math easier.

EDIT2: Reading through the docs on SQLite data types, it seems that you might be able to just make the "signature" field span 26 columns of type INTEGER and SQLite will do the right thing and only use as many bits as required to store the value.

Do I reckon correctly that you have about 450K words like that in your database ?

I've got no clue about iPhone, neither serious about sqlitem but... as long as sqlite does not allow for a way to save the file as gz right away (it maybe already does internally? no, does not look like that when you say it's about 135 b per entry. not even with both indexes), I would move away from the table approach, save it "manually" in a dictionary approach compression and build the rest on the fly and in memory. That should perform VERY well on your type of data.

Wait... Are you using that signature to allow for fulltextsearching or mistyping recogition ? Would full text search on sqlite not obsolete that field ?

As noted storing "Signature" more efficiently seems like a good idea.

However, it also seems like you could gain a ton of space savings by using some kind of lookup table for words - since you seem to be taking a root word and then appending "er", "ed", "es", etc why not have a column with a numeric ID that references a root word from a separate lookup table, and then a separate column with a numeric ID that references a table of common word suffixes that would be appended to the base word.

If there were any tricks around storing shorthand versions of signatures for multiple entries with a single root word, you could also employ those to reduce the size of stored signatures (not sure what algorithm is producing those values)

This also seems to make a lot of sense to me as you have the "word" column as a primary key, but do not even index it - just create a separate numeric column that is the primary ID for the table.

mhmm... an iPhone... doesn't it have a permanent data connection ? I think this is where a webapplication/webservice can jump in snugly. Move most of your business logic to the webserver (he's gonna have real SQL with FTS and looooots of memory) and fetch that info online to the client on the device.

As mentioned elsewhere, lose the indexes on the boolean columns, they will almost certainly be slower (if used at all) than a table scan and are going to use space needlessly.

I'd consider applying a simple compression to the words, Huffman coding is pretty good for this sort of thing. Also, I'd look at the signatures: sort the columns in letter frequency order and don't bother storing trailing zeroes, which can be implied. I guess you could Huffman-encode those, too.

Always assuming your encoded strings don't upset SQLite, of course.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top