Question

edit: merci beaucoup pour toutes les réponses. Voici les résultats après avoir appliqué les optimisations jusqu'ici:

  • Passage au tri des caractères et au codage de la longueur d'exécution - nouvelle taille de base de données 42M
  • Suppression des index sur les booléens - nouvelle taille de base de données 33M

La partie la plus intéressante est que cela n’a nécessité aucune modification du code iphone

J'ai une application iPhone avec un grand dictionnaire au format sqlite (lecture seule). Je cherche des idées pour réduire la taille du fichier de base de données, qui est actuellement très volumineux.

Voici le nombre d'entrées et la taille résultante du DB 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

... une moyenne d'environ 135 octets par entrée.

Voici mon schéma de base de données:

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)

Voici quelques exemples de données:

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

Le dernier champ représente les fréquences des lettres pour la récupération d'anagramme (chaque position est dans la plage 0..9). Les deux booléens représentent des dictionnaires secondaires.

Je dois faire des requêtes telles que:

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

L’une de mes idées est de coder plus efficacement les fréquences des lettres, par exemple. binaire les encoder comme un blob (peut-être avec RLE car il y a beaucoup de zéros?). Des idées sur la meilleure façon d’y parvenir, ou d’autres idées pour réduire la taille? Je construis la DB en ruby ??et je la lis au téléphone dans l’objectif C.

Existe-t-il également un moyen d'obtenir des statistiques sur la base de données afin que je puisse voir ce qui utilise le plus d'espace?

Était-ce utile?

La solution

Je ne suis pas au courant de tous les cas d'utilisation du champ de signature, mais il semble que le stockage d'une version alphabétique du mot serait préférable.

Autres conseils

Avez-vous essayé de taper le "vide" " commande pour vous assurer que vous n'avez pas d'espace supplémentaire dans la base de données que vous avez oublié de reprendre?

Supprimez les index sur sowpods et twl - ils n’aideront probablement pas votre temps de requête et prendront certainement beaucoup de place.

Vous pouvez obtenir des statistiques sur la base de données à l'aide de sqlite3_analyzer à partir de la page de SQLite. .

Comme approche totalement différente, vous pouvez utiliser un filtre de bloom au lieu d'un filtre complet. base de données. Fondamentalement, un filtre de bloom consiste en un ensemble de fonctions de hachage, chacune associée à un champ de bits. Pour chaque mot légal, chaque fonction de hachage est évaluée et le bit correspondant du champ de bits correspondant est défini. L’inconvénient est qu’il est théoriquement possible d’obtenir des faux positifs, mais ceux-ci peuvent être minimisés / pratiquement éliminés avec suffisamment de hachages. Le côté plus est un gain de place considérable.

Le créateur de SQLite vend une version de SQLite qui inclut la compression de la base de données (et le cryptage). Ce serait parfait.

Votre meilleur choix est d'utiliser la compression, que SQLite ne prend malheureusement pas en charge de manière native à ce stade. Heureusement, quelqu'un a pris le temps de développer une extension de compression qui pourrait être ce dont vous avez besoin.

Sinon, je vous recommande de stocker vos données principalement au format compressé et de les décompresser à la volée.

En tant que champ de texte, signature utilise actuellement au moins 26 * 8 octets par entrée (208 octets), mais si vous deviez regrouper les données dans un champ binaire, vous pourriez probablement vous en tirer. 3 bits par lettre (réduisant votre fréquence maximale par lettre à 7). Cela signifierait que vous pourriez compresser la signature entière en 26 * 3 bits = 78 bits = 10 octets. Même si vous utilisiez 4 bits par lettre (pour une fréquence maximale de 15 par lettre), vous n’utiliseriez que 104 bits (13 octets).

EDIT: Après un peu plus de réflexion, je pense que 4 bits par lettre (au lieu de 3) serait une meilleure idée car cela faciliterait les calculs binaires.

EDIT2: en parcourant la documentation sur les types de données SQLite , il semble que vous soyez capable de simplement faire la "signature" field span 26 colonnes de type INTEGER et SQLite agissent correctement et n'utilisent que le nombre de bits nécessaire pour stocker la valeur.

Est-ce que je pense correctement que vous avez environ 450 000 mots de ce type dans votre base de données?

Je n'ai aucune idée de l'iPhone, ni sérieux de sqlitem mais ... tant que sqlite ne permet pas un moyen de sauvegarder le fichier en tant que gz tout de suite (il le fait peut-être déjà en interne? non, ne semble pas comme si vous disiez environ 135 milliards par entrée (même avec les deux index), je m'éloignerais de l'approche table, je la sauvegarde "manuellement". dans une compression de l'approche par dictionnaire et créer le reste à la volée et en mémoire. Cela devrait fonctionner TRÈS bien sur votre type de données.

Patientez ... Utilisez-vous cette signature pour permettre la reconnaissance de la recherche en texte intégral ou la saisie de type incorrect? La la recherche en texte intégral sur sqlite ne serait-il pas obsolète?

Comme noté, en conservant & Signature; Signature " semble plus efficace comme une bonne idée.

Cependant, il semble également que vous pourriez gagner une tonne d'économies d'espace en utilisant une sorte de table de recherche pour les mots - puisque vous semblez prendre un mot racine puis ajouter le mot "er", "ed", " ; es " ;, etc pourquoi ne pas avoir une colonne avec un ID numérique qui référence un mot racine d’une table de recherche séparée, puis une colonne séparée avec un ID numérique qui fait référence à une table de suffixes de mots courants qui seraient ajoutés au mot de base .

S'il existe des astuces concernant le stockage de versions abrégées de signatures pour plusieurs entrées avec un seul mot racine, vous pouvez également les utiliser pour réduire la taille des signatures stockées (vous ne savez pas quel algorithme produit ces valeurs)

Cela semble également beaucoup de sens pour moi, car vous avez le "mot". colonne en tant que clé primaire, mais ne l'indexez même pas - créez simplement une colonne numérique distincte qui constitue l'ID principal de la table.

mhmm ... un iPhone ... n'a-t-il pas une connexion de données permanente? Je pense que c’est là qu’une application Web / service Web peut s’adapter parfaitement. Transférez l'essentiel de votre logique métier sur le serveur Web (il aura du vrai SQL avec FTS et de la mémoire) et récupérez ces informations en ligne sur le client de l'appareil.

Comme mentionné ailleurs, perdez les index sur les colonnes booléennes, ils seront presque certainement plus lents (s'ils sont utilisés du tout) qu'un balayage de table et vont utiliser de l'espace inutilement.

J'aimerais envisager d'appliquer une simple compression aux mots, le le codage de Huffman est plutôt bon. pour ce genre de chose. De plus, je regarderais les signatures: triez les colonnes par ordre de fréquence des lettres et ne vous souciez pas de stocker les zéros, ce qui peut être implicite. Je suppose que vous pourriez aussi les encoder avec Huffman.

En supposant toujours que vos chaînes encodées ne contrarient pas SQLite, bien sûr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top