Le problème est le suivant:Comment extraire efficacement le nombre de chaque élément d'un grand ensemble de données?
- Entrée: Tous les articles de Wikipedia (33GB de texte)
- Sortie: Nombre de chaque skipgram mots (n-grammes avec skips maximum de k) de Wikipedia dans le fichier SQLite.
schéma de la table de sortie est:
CREATE TABLE [tokens] ([token] TEXT UNIQUE NOT NULL PRIMARY KEY, [count] INTEGER NOT NULL
L'approche naïve est que pour chaque skipgram nous créons un nouveau record dans le compteur de table ou incrément dans le dossier existant:
INSERT OR REPLACE INTO [tokens] VALUES (@token, COALESCE((SELECT count FROM [tokens] WHERE [email protected]), 0) + 1)
Le problème avec cette approche est que l'index est constamment mis à jour et lorsque la base de données passe à plusieurs giga, ces mises à jour sont très lentes. Nous pouvons résoudre cela en créant la table "jetons" sans index et en ajoutant l'index à la fin du traitement.
Le problème est que l'instruction select SELECT count FROM [tokens] WHERE [email protected]
qui doit analyser la table réduit considérablement les performances.
La meilleure méthode que je l'ai trouvé à ce jour est la suite (j'utilise C#):
Créer une
Dictionary<string,int>
pour compter les jetons.Ajoutez des jetons à ce dictionnaire jusqu'à ce qu'il devienne trop grand pour tenir dans la RAM.
Insérer (ne pas mettre à jour) les jetons du dictionnaire pour une table temporaire sans index. Le tableau a suivant le schéma:
CREATE TABLE [temp] ([token] TEXT, [count] INTEGER)
S'il y a plus de jetons, désactivez le dictionnaire et passez à l'étape 2.
jetons de copie de table temporaire à la table des jetons:
INSERT INTO [tokens] SELECT [token], SUM([count]) AS [count] FROM [temp] GROUP BY [token]
Cette méthode prend seulement "24 heures" pour traiter l'ensemble de données, mais je crois que ce n'est pas la meilleure approche parce que l'étape 5 prend 22 heures sur 24.
Connaissez-vous une approche alternative qui peut résoudre ce problème?
P.S. Mon application est à un seul thread et je fais les insertions ci-dessus en lots (100000 par lot) dans la transaction.
Votre application est-elle multithread? –