Guide de développement

Local Navigation

Performances des bases de données SQLite

Par rapport à des ordinateurs, les terminaux mobiles fournissent un environnement très contraint pour les bases de données SQLite. Pour atteindre des performances optimales sur un smartphone BlackBerry, tenez compte des contraintes suivantes :

  • La limite dynamique de mémoire est 16 Mo. Cette limite fait référence à la quantité de RAM disponible pour une base de données SQLite afin de stocker les structures de données internes pour les schémas et les transactions. Le schéma de base de données complet est chargé en mémoire lorsqu'une base de données SQLite est ouverte. Il persiste jusqu'à la fermeture de la base de données.

  • La longueur maximale de requête SQL est 1 Mo.

  • Le nombre maximal de bases de données pouvant être ouvertes en même temps est environ 50. L'API de base de données utilise un mode cache partagé pour utiliser efficacement la mémoire pour plusieurs connexions vers la même base de données.

  • Une seule connexion de base de données en lecture-écriture vers une base de données SQLite est possible à la fois. Les autres connexions de base de données sont en lecture seule.

Lorsque vous utilisez les méthodes Database.createBlobOutputStream et Database.createBlobInputStream pour lire et écrire des objets binaires de grande taille (blobs), la mémoire disponible pour SQLite ne limite pas la taille du blob que vous pouvez utiliser : votre jeu de résultats n'est pas limité à 1 Mo.

Vous pouvez suivre l'utilisation de la mémoire pour chaque connexion de base de données à l'aide des méthodes suivantes : Database.getCacheUsed, Database.getSchemaUsed et Database.getStatementUsed.

Présentation de SQLite en tant que service

Sur un smartphone BlackBerry, SQLite s'exécute en tant que service. Les opérations de base de données utilisent un service d'exécution pour transférer des données entre Java et le code natif. Il existe une limite de 1 Mo sur la quantité de données qui peut être transférée via le service d'exécution. Le service d'exécution peut fournir d'excellentes performances pour les opérations de base de données, mais ces performances peuvent diminuer en cas d'utilisation inappropriée.

Lorsque vous créez une instruction préparée pour insérer ou mettre à jour des données, vous devriez utiliser les méthodes Statement.executeInsert ou Statement.executeUpdate pour réduire le nombre d'appels via le service d'exécution. Ces méthodes exécutent les opérations suivantes en code natif :

  • Liaison des paramètres SQL
  • Exécution de l'instruction
  • Réinitialisation de l'instruction
  • Suppression des liaisons
  • Renvoi du dernier ID de ligne inséré (executeInsert uniquement)

Lorsque vous exécutez une requête qui ne renvoie pas de jeu de résultats et que vous ne liez pas de paramètres, vous devez utiliser la méthode Database.executeStatement, qui réduit le nombre d'appels via le service d'exécution en exécutant les opérations suivantes en code natif :

  • Préparation de l'instruction
  • Exécution de l'instruction
  • Finalisation de l'instruction

Lorsque vous exécutez une requête qui renvoie des jeux de résultats à l'aide de la méthode Statement.getCursor, vous pouvez récupérer un nombre spécifié de lignes en utilisant la méthode Statement.setCursorBufferSize. Cette méthode réduit l'utilisation du service d'exécution. Lorsque le curseur se déplace au-delà de l'ensemble mis en mémoire-tampon, un nouveau lot de lignes est automatiquement extrait. Vous pouvez récupérer le nombre de lignes qu'un curseur mettra en mémoire-tampon avec la méthode Statement.getCursorBufferSize.

Lorsque vous récupérez des valeurs de nombre entier à utiliser en tant que clés dans une autre requête, vous pouvez utiliser les méthodes Statement.getIntegers et Statement.getLongs. Ces méthodes simplifient et optimisent la récupération de colonnes de nombres entiers.

Méthode recommandée : optimisation des performances de la base de données SQLite

Prenez en compte les recommandations suivantes :

Méthode recommandée Description

Utilisez le mode de journalisation approprié.

Par défaut, un journal de restauration est utilisé pour enregistrer les transactions, mais vous pouvez choisir d'utiliser plutôt un journal WAL (Write-Ahead Log). Le journal WAL offre une meilleure simultanéité et est plus rapide que le journal de restauration dans la plupart des situations car l'écriture dans la base de données ne bloque pas la lecture. Toutefois, le journal WAL utilise plus d'identificateurs de fichier. Le journal WAL utilise jusqu'à trois identificateurs de fichier pouvant demeurer pendant de longues périodes, tandis que le journal de restauration n'en utilise qu'un, voire parfois deux, lors de l'écriture des transactions. Pour définir le mode de journalisation sur WAL, exécutez l'instruction SQL "PRAGMA journal_mode = WAL;".

Envisagez d'assouplir les contraintes de sécurité pour les tables.

Lorsque l'intégrité des données n'est pas une inquiétude, envisagez d'utiliser des commandes Pragma pour ne pas spécifier de journal et désactiver le mode synchrone. Par exemple, PRAGMA journal_mode=OFF et PRAGMA synchronous=OFF.

Test

Si vous avez l'intention de créer une base de données avec un grand schéma ou d'insérer des objets binaires de grande taille, testez la base de données sur vos smartphones BlackBerry cible pour vous assurer qu'ils disposent d'assez de mémoire.

Stockez le moins de données possible.

La majorité du temps de traitement des bases de données SQLite est occupé par la lecture et l'écriture dans le stockage. Moins de données signifie généralement moins de lecture et d'écriture. Le moteur de base de données SQLite met en cache les pages de base de données souvent utilisées. En stockant moins de données, le moteur de base de données SQLite a plus de chances de récupérer les données du cache plus rapidement que celles du stockage.

Regroupez les instructions avec des transactions explicites.

Si vous n'utilisez pas de transactions explicites, une transaction est créée pour chaque instruction que vous exécutez. Ce comportement par défaut est inefficace. Cela requiert l'ouverture, la réouverture, l'écriture et la fermeture du fichier journal pour chaque instruction. Avec les transactions explicites, vous pouvez regrouper des instructions pour améliorer l'efficacité. Vous pouvez exécuter plusieurs instructions dans une transaction en plaçant Database.beginTransaction et Database.commitTransaction autour d'un groupe d'instructions.

Créez des index efficaces.

Les index peuvent réduire considérablement le temps d'analyse d'un tableau. Voici quelques remarques à propos de la création efficace d'index :

  • Les index peuvent améliorer des performances pour les requêtes en lecture seule telles que SELECT, mais peuvent réduire les performances pour les requêtes qui modifient des lignes. Ne prenez en compte que les tables d'indexation qui sont rarement mises à jour.
  • L'ordre des colonnes dans un index affecte les performances. Les colonnes qui sont généralement utilisées dans les clauses WHERE doivent être placées en premier, suivies des colonnes généralement utilisées dans les clauses ORDER BY.
  • Pour les colonnes qui contiennent des données extraites, créez un index de couverture.
  • Évitez les index en double. Le moteur de base de données SQLite crée automatiquement des index pour les colonnes avec les contraintes UNIQUE ou PRIMARY KEY.
  • Les colonnes déclarées comme INTEGER PRIMARY KEY entraînent des requêtes plus rapides, car elles accèdent directement aux données de table.

Réduisez la taille des lignes.

En présence d'une colonne très large, songez à la placer dans un tableau individuel.

Stockez les objets binaires de grande taille (blob) de façon appropriée.

Si vos données incluent des objets binaires de grande taille (blob), effectuez leur lecture et leur écriture à l'aide des objets InputStream et OutputStream en utilisant createBlobInputStream et createBlobOutputStream.

Vous pouvez également envisager de stocker chaque blob dans une table séparée. Si ces blobs sont très volumineux, vous pouvez les stocker en tant que fichiers en dehors de la base de données et stocker le chemin vers chaque fichier dans la base de données. Toutefois, cette pratique génère une surcharge système à cause des recherches de noms de fichiers.

Envisagez d'utiliser des tables temporaires.

Si vous n'avez pas besoin que les données soient disponibles après redémarrage du smartphone, utilisez l'instruction CREATE TEMP TABLE au lieu de CREATE TABLE.

Utilisez des paramètres SQL.

Pour exécuter une série d'instructions de même format, préparez d'abord une instruction générique utilisant des paramètres SQL. Vous pouvez exécuter les instructions en itérant parmi les valeurs variables et en liant les valeurs aux variables nommées dans chaque itération.

Évitez les sous-requêtes.

Dans certains cas, le moteur de base de données SQLite stocke les résultats des sous-requêtes dans un fichier temporaire, ce qui peut ralentir le traitement.

Défragmentez la base de données.

Utilisez la commande SQLite VACUUM pour défragmenter la base de données. Ce processus réduit également la taille du fichier de base de données.

Tenez compte de l'ordre des colonnes dans les déclarations de tableau.

L'ordre des colonnes dans une déclaration de tableau affecte les performances, surtout en l'absence d'index, parce que le moteur de base de données SQLite numérise les colonnes dans l'ordre défini dans la déclaration de tableau. Les colonnes contenant de petites quantités de données souvent utilisées doivent être placées avant les colonnes contenant de grandes quantités de données rarement utilisées.

Utilisez des méthodes par lots.

Les méthodes par lots suivantes utilisent de manière efficace le service d'exécution :

Pour plus d'informations, consultez la sectionPrésentation de SQLite en tant que service.


Ces informations vous ont-elles été utiles ? Envoyez-nous vos commentaires.