Вопрос

Редактировать:большое спасибо за все ответы.Вот результаты после применения оптимизаций на данный момент:

  • Переключение на сортировку символов и кодировку длины выполнения - новый размер базы данных 42M
  • Удаление индексов для логических значений - новый размер базы данных 33M

Действительно приятная часть заключается в том, что для этого не потребовалось никаких изменений в коде iphone

У меня есть приложение для iPhone с большим словарем, хранящимся в формате sqlite (только для чтения).Я ищу идеи по уменьшению размера файла базы данных, который в настоящее время очень велик.

Вот количество записей и результирующий размер базы данных sqlite:

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 байт на запись.

Вот моя схема базы данных:

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')

Одна из идей, которые у меня есть, состоит в том, чтобы более эффективно кодировать частоты букв, напримердвоичное кодирование их в виде большого двоичного объекта (возможно, с помощью RLE, поскольку там много нулей?).Есть какие-нибудь идеи о том, как лучше всего этого добиться, или другие идеи по уменьшению размера?Я создаю базу данных на ruby и читаю ее по телефону в objective C.

Также есть ли какой-нибудь способ получить статистику по базе данных, чтобы я мог видеть, что занимает больше всего места?

Это было полезно?

Решение

Мне неясны все варианты использования поля подписи, но, похоже, было бы полезно сохранить вместо него алфавитную версию слова.

Другие советы

Вы пробовали вводить команду "vacuum", чтобы убедиться, что у вас нет лишнего места в базе данных, которую вы забыли повторно заполнить?

Удалите индексы на sowpods и twl - они, вероятно, не способствуют ускорению выполнения запросов и определенно занимают много места.

Вы можете получить статистику по базе данных, используя sqlite3_analyzer - анализатор из самого Страница загрузки SQLite.

В качестве совершенно другого подхода вы могли бы попробовать использовать фильтр цветения вместо всеобъемлющей базы данных.По сути, фильтр Блума состоит из набора хэш-функций, каждая из которых связана с битовым полем.Для каждого юридического слова вычисляется каждая хэш-функция и устанавливается соответствующий бит в соответствующем битовом поле.Недостатком является то, что теоретически возможно получение ложных срабатываний, но их можно свести к минимуму / практически устранить при достаточном количестве хэшей.Плюсом является огромная экономия места.

Создатель SQLite продает версию SQLite, которая включает сжатие базы данных (и шифрование).Это было бы идеально.

Лучше всего использовать сжатие, которое, к сожалению, на данный момент SQLite изначально не поддерживает.К счастью, кто-то нашел время разработать расширение при сжатии для того, что могло бы быть тем, что вам нужно.

В противном случае я бы рекомендовал хранить ваши данные в основном в сжатом формате и распаковывать на лету.

В виде текстового поля, signature в настоящее время используется не менее 26 * 8 байт на запись (208 байт), но если бы вы упаковали данные в битовое поле, вы, вероятно, могли бы обойтись всего 3 битами на букву (сократив максимальную частоту на букву до 7).Это означало бы, что вы могли бы упаковать всю подпись в 26 * 3 бита = 78 бит = 10 байт.Даже если бы вы использовали 4 бита на букву (при максимальной частоте 15 на букву), вы бы использовали только 104 бита (13 байт).

Редактировать:Еще немного подумав, я думаю, что 4 бита на букву (вместо 3) было бы лучшей идеей, потому что это упростило бы двоичную математику.

РЕДАКТИРОВАТЬ 2:Чтение документов по Типы данных SQLite, кажется, что вы могли бы просто сделать так, чтобы поле "подпись" охватывало 26 столбцов типа INTEGER, и SQLite поступит правильно и будет использовать только столько битов, сколько требуется для хранения значения.

Правильно ли я считаю, что у вас в базе данных около 450 тысяч подобных слов?

Я понятия не имею ни об iPhone, ни о серьезном отношении к sqlitem, но...пока sqlite не позволяет сразу сохранить файл как gz (возможно, это уже делается внутренне?нет, так не выглядит, когда вы говорите, что это около 135 миллиардов долларов за запись.даже с обоими индексами), я бы отошел от табличного подхода, сохранив его "вручную" в сжатие словарного подхода а остальное создавайте "на лету" и в памяти.Это должно очень хорошо работать с вашим типом данных.

Подожди...Используете ли вы эту подпись для обеспечения полнотекстового поиска или распознавания опечаток ?Бы полнотекстовый поиск в sqlite это поле не устарело?

Как уже отмечалось, более эффективное хранение "Подписи" кажется хорошей идеей.

Однако также кажется, что вы могли бы значительно сэкономить место, используя какую-то таблицу поиска для слов - поскольку вы, похоже, берете корневое слово и затем добавляете "er", "ed", "es" и т.д., почему бы не создать столбец с числовым идентификатором, который ссылается на корневое слово из отдельной таблицы поиска, а затем отдельный столбец с числовым идентификатором, который ссылается на таблицу общих суффиксов слов, которые были бы добавлены к базовому слову.

Если бы существовали какие-либо хитрости, связанные с хранением сокращенных версий подписей для нескольких записей с одним корневым словом, вы также могли бы использовать их для уменьшения размера хранимых подписей (не уверен, какой алгоритм создает эти значения)

Мне также кажется, что это имеет большой смысл, поскольку у вас есть столбец "word" в качестве первичного ключа, но вы даже не индексируете его - просто создайте отдельный числовой столбец, который является основным идентификатором для таблицы.

ммм...айфон...разве у него нет постоянного подключения для передачи данных?Я думаю, что именно здесь веб-приложение / веб-сервис может удобно подключиться.Переместите большую часть своей бизнес-логики на веб-сервер (у него будет реальный SQL с FTS и ооочень много памяти) и извлеките эту информацию онлайн клиенту на устройстве.

Как упоминалось в другом месте, потеряйте индексы в логических столбцах, они почти наверняка будут работать медленнее (если вообще будут использоваться), чем сканирование таблицы, и будут использовать пространство без необходимости.

Я бы подумал о применении простого сжатия к словам, Кодирование Хаффмана довольно хорош для такого рода вещей.Кроме того, я бы посмотрел на подписи:отсортируйте столбцы в порядке частоты следования букв и не утруждайте себя сохранением конечных нулей, что может быть подразумеваемо.Я думаю, вы могли бы и их закодировать по Хаффману.

Конечно, всегда предполагая, что ваши закодированные строки не нарушают SQLite.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top