web-dev-qa-db-fra.com

Quelles sont les caractéristiques de performance de sqlite avec des fichiers de base de données très volumineux?

Je sais que sqlite ne fonctionne pas bien avec des fichiers de base de données extrêmement volumineux, même lorsqu'ils sont pris en charge (il existait un commentaire sur le site Web de sqlite indiquant que si vous avez besoin d'une taille de fichier supérieure à 1 Go, vous pouvez envisager d'utiliser un fichier d'entreprise .dd. ne le trouve plus, peut-être lié à une ancienne version de sqlite).

Toutefois, je souhaiterais avoir une idée de la gravité de la situation avant d’envisager d’autres solutions.

Je parle de fichiers de données sqlite dans la plage de plusieurs gigaoctets, à partir de 2 Go. Quelqu'un a-t-il une expérience avec ceci? Des conseils/idées?

315
Snazzer

J'ai donc fait quelques tests avec sqlite pour de très gros fichiers et je suis parvenu à des conclusions (du moins pour mon application spécifique).

Les tests impliquent un seul fichier sqlite avec une seule table ou plusieurs tables. Chaque table avait environ 8 colonnes, presque tous les entiers et 4 index.

L'idée était d'insérer suffisamment de données jusqu'à ce que les fichiers sqlite atteignent environ 50 Go.

Table unique

J'ai essayé d'insérer plusieurs lignes dans un fichier sqlite avec une seule table. Lorsque le fichier faisait environ 7 Go (désolé, je ne peux pas préciser le nombre de lignes), les insertions prenaient beaucoup trop de temps. J'avais estimé que mon test pour insérer toutes mes données prendrait environ 24 heures, mais il ne s'est pas terminé même après 48 heures.

Ceci m'amène à conclure qu'une seule et très grande table sqlite aura des problèmes d'insertion et probablement aussi d'autres opérations.

Je suppose que ce n’est pas une surprise, car la table s’agrandit, l’insertion et la mise à jour de tous les index prend plus de temps.

Plusieurs tables

J'ai ensuite essayé de scinder les données temporellement sur plusieurs tables, une table par jour. Les données de la table 1 originale ont été divisées en ~ 700 tables.

Cette configuration n’a posé aucun problème lors de l’insertion, elle n’a pas pris plus de temps, puisqu’un nouveau tableau a été créé pour chaque jour.

Problèmes de vide

Comme l'a souligné i_like_caffeine, la commande VACUUM pose un problème lorsque le fichier sqlite est volumineux. Avec la multiplication des insertions/suppressions, la fragmentation du fichier sur le disque s’aggravera. L’objectif est donc de procéder périodiquement à une opération VACUUM afin d’optimiser le fichier et de récupérer de l’espace.

Cependant, comme indiqué par documentation , une copie complète de la base de données est créée pour faire le vide, ce qui prend beaucoup de temps. Donc, plus la base de données est petite, plus cette opération se terminera rapidement.

Conclusions

Pour mon application spécifique, je vais probablement répartir les données sur plusieurs fichiers db, un par jour, pour obtenir le meilleur des performances du vide et de la vitesse d'insertion/suppression.

Cela complique les requêtes, mais pour moi, il est intéressant de pouvoir indexer autant de données. Un avantage supplémentaire est que je peux simplement supprimer un fichier de base de données complet pour supprimer une journée de données (opération courante pour mon application).

Je devrais probablement aussi surveiller la taille des tables par fichier pour voir quand la vitesse deviendrait un problème.

C'est dommage qu'il ne semble pas y avoir de méthode de vide incrémental autre que vide automatique . Je ne peux pas l'utiliser car mon objectif pour Vacuum est de défragmenter le fichier (l'espace fichier n'est pas grave), ce que ne fait pas Vacuum. En fait, la documentation indique que cela peut aggraver la fragmentation. Je dois donc périodiquement faire le vide complet dans le dossier.

235
Snazzer

Nous utilisons DBS de 50 Go + sur notre plateforme. pas se plaindre fonctionne très bien. Assurez-vous de tout faire correctement! Utilisez-vous des instructions prédéfinies? * SQLITE 3.7.3

  1. Transactions
  2. Déclarations pré faites
  3. Appliquer ces paramètres (juste après la création de la base de données)

    PRAGMA main.page_size = 4096;
    PRAGMA main.cache_size=10000;
    PRAGMA main.locking_mode=EXCLUSIVE;
    PRAGMA main.synchronous=NORMAL;
    PRAGMA main.journal_mode=WAL;
    PRAGMA main.cache_size=5000;
    

J'espère que cela aidera les autres, fonctionne très bien ici

156
Alex

J'ai créé des bases de données SQLite d'une taille allant jusqu'à 3,5 Go, sans aucun problème de performances notable. Si je me souviens bien, je pense que SQLite2 a peut-être eu des limites plus basses, mais je ne pense pas que SQLite3 pose de tels problèmes.

Selon la page SQLite Limits , la taille maximale de chaque page de base de données est de 32 Ko. Et le maximum de pages dans une base de données est 1024 ^ 3. Donc, selon mes calculs, la taille maximale est de 32 téraoctets. Je pense que vous allez atteindre les limites de votre système de fichiers avant de toucher SQLite!

62
Paul Lefebvre

La plupart des raisons pour lesquelles vos insertions ont pris> 48 heures sont dues à vos index. Il est incroyablement plus rapide de:

1 - Supprimer tous les index 2 - Effectuer toutes les insertions 3 - Créer à nouveau des index

50
user352992

Outre la recommandation habituelle:

  1. Drop index pour l'insertion en vrac.
  2. Inserts/mises à jour par lots dans les transactions importantes.
  3. Réglez votre mémoire tampon/désactivez le journal/w PRAGMA.
  4. Utilisez un ordinateur 64 bits (pour pouvoir utiliser beaucoup de cache ™).
  5. [ajouté en juillet 2014] Utilisez expression de table commune (CTE) au lieu d'exécuter plusieurs requêtes SQL! Nécessite la version 3.8ite de SQLite.

J'ai appris ce qui suit de mon expérience avec SQLite3:

  1. Pour une vitesse d'insertion maximale, n'utilisez pas de schéma avec une contrainte de colonne. (Modifier la table plus tard si nécessaire Vous ne pouvez pas ajouter de contraintes avec ALTER TABLE).
  2. Optimisez votre schéma pour stocker ce dont vous avez besoin. Parfois, cela signifie décomposer les tables et/ou même compresser/transformer vos données avant de les insérer dans la base de données. Un bon exemple consiste à stocker les adresses IP sous forme de nombres entiers (longs).
  3. Une table par fichier de base de données - pour réduire les conflits de verrous. (Utilisez ATTACH DATABASE si vous souhaitez avoir un seul objet de connexion.
  4. SQLite peut stocker différents types de données dans la même colonne (typage dynamique), utilisez-le à votre avantage.

Question/commentaire bienvenue. ;-)

30
Lester Cheung

J'ai une base de données SQLite de 7 Go. Pour effectuer une requête particulière avec une jointure interne, il faut 2.6s. Pour accélérer le processus, j'ai essayé d'ajouter des index. En fonction du ou des index que j'ai ajoutés, la requête est parfois descendue à 0.1s et parfois jusqu'à 7s. Je pense que le problème dans mon cas était que si une colonne est hautement dupliquée, l'ajout d'un index dégrade les performances :(

8
Mike Oxynormas

Je pense que les principales plaintes concernant la mise à l'échelle de sqlite sont les suivantes:

  1. Processus unique d'écriture.
  2. Pas de reflet.
  3. Pas de réplication.
8
Unknown

J'ai rencontré des problèmes avec les gros fichiers sqlite lors de l'utilisation de la commande vacuum.

Je n'ai pas encore essayé la fonctionnalité auto_vacuum. Si vous vous attendez à mettre à jour et à supprimer des données souvent, cela vaut la peine d'être examiné.

6
eodonohoe