10
votes

Optimisation SQLite pour l'application Android

Nous avons environ 7-8 tables dans notre application Android ayant chacune environ 8 colonnes sur une moyenne. Les opérations de lecture et d'écriture sont effectuées sur la base de données et j'essaye et essaie de trouver des moyens d'améliorer les performances de la couche DataAccess. Donc, loin j'ai essayé ce qui suit:

  1. Utilisez des arguments positionnels dans les clauses (raison: de sorte que SQLite utilise le même plan d'exécution)
  2. enfermez les inserts et la mise à jour avec les transactions (raison: chaque opération de dB est jointe dans une transaction par défaut. Cela supprimera ce surcharge)
  3. Indexation: Je n'ai créé aucun index explicite autre que celles créées par défaut sur la clé primaire et les colonnes de clés uniques. (Raison: l'indexation améliorera le temps de recherche)

    J'ai mentionné mes hypothèses en paranthèse; S'il vous plaît corrigez-moi si je me trompe.

    questions:

    1. Puis-je ajouter quelque chose d'autre à cette liste? J'ai lu quelque part que d'éviter l'utilisation de DB-Journal peut améliorer la performance des mises à jour? Est-ce un mythe ou un fait? Comment cela peut-il être fait, s'il est recommandé?

    2. sont des transactions imbriquées autorisées dans SQLite3? Comment affectent-ils les performances? La chose est que j'ai une fonction qui exécute une mise à jour dans une boucle, j'ai donc joint la boucle dans un bloc de transaction. Parfois, cette fonction est appelée d'une autre boucle à l'intérieur d'une autre fonction. La fonction d'appel entoure également la boucle dans un bloc de transaction. Comment une telle nidification de transactions affecte la performance?

    3. Les clauses de la recherche de mes requêtes utilisent plus d'une colonnes pour construire le prédicat. Ces colonnes ne peuvent pas nécessairement par une clé primaire ou une colonne unique. Devrais-je créer des indices sur ces colonnes aussi? Est-ce une bonne idée de créer plusieurs indices pour une telle table?


0 commentaires

4 Réponses :


1
votes

J'ajouterais ceci:

  1. Utilisation de RawQuery () au lieu de bâtir à l'aide de contenusValues ​​attachera dans certains cas. hors de bien sûr, il est un peu fastidieux d'écrire une requête crue.

  2. Si vous avez beaucoup de données de type String / Type, envisagez de créer des tables virtuelles à l'aide de la recherche de texte intégral (FTS3), qui peut exécuter une requête plus rapide. Vous pouvez rechercher dans Google pour les améliorations exactes de la vitesse.


0 commentaires

13
votes
  1. épinglez exactement quelles requêtes vous devez optimiser. Prenez une copie d'une base de données typique et utilisez la requête REP vers TIME. Utilisez-le pour comparer les gains à mesure que vous optimisez.

  2. Utilisez Analyser pour permettre à SQLite's Query Planner de travailler plus efficacement.

  3. pour SELECT S et MISE UPDATE S, les index peuvent les choses, mais uniquement si les index que vous créez peuvent réellement être utilisés par les requêtes que vous avez besoin de vitesse que vous avez besoin de vitesse en haut. Utilisez Expliquer le plan de requête sur vos requêtes pour voir quel index serait utilisé ou si la requête nécessite une analyse de la table complète. Pour les grandes tables, une analyse de table complète est mauvaise et vous voulez probablement un index. Un seul index sera utilisé sur une requête donnée. Si vous avez plusieurs prédicats, l'indice qui sera utilisé est celui qui devrait réduire le résultat défini le plus (basé sur analyser ). Vous pouvez avoir des index contenant plusieurs colonnes (pour aider les requêtes à plusieurs prédicats). Si vous avez des index avec plusieurs colonnes, ils ne sont utilisables que si les prédicats correspondent à l'index de gauche à droite sans lacunes (mais les colonnes inutilisées à la fin sont correctes). Si vous utilisez un prédicat de commande ( << / code>, <= , > etc.) puis qui doit être dans la dernière colonne utilisée de l'index. Utilisation des deux prédicats et commander par nécessite à la fois un index et une sqlite ne peut en utiliser qu'un seul point, afin que cela puisse être un point où la performance souffre. Plus vous aurez d'index, plus votre insertion S sera, de sorte que vous devrez élaborer le meilleur compromis pour votre situation.

  4. Si vous avez des questions plus complexes qui ne peuvent utiliser aucun index que vous pourriez créer, vous pouvez désalminaliser votre schéma, structurer vos données de manière à ce que les requêtes soient simples et que vous puissiez répondre en utilisant des index.

  5. Si vous faites un grand nombre de insérer S, essayez de supprimer les index et de les recréer à la fin. Vous devrez comparer ceci.

  6. sqlite prend en charge les transactions imbriquées à l'aide de points de sauvegarde, mais je ne suis pas sûr que Vous gagnerez tout ce qui existe performance.

  7. vous pouvez Gagnez beaucoup de vitesse en compromettant sur l'intégrité des données . Si vous pouvez vous rétablir de la corruption de base de données vous-même, cela pourrait fonctionner pour vous. Vous ne pouvez peut-être pas faire cela que lorsque vous faites des opérations intensives que vous pouvez récupérer de manuellement.

    Je ne sais pas à quel point vous pouvez vous rendre à une application Android. Il y a un plus détaillé de guide pour optimiser SQLite en général dans la documentation SQLITE.


1 commentaires

Merci d'avoir pris le temps de répondre à cette question.



10
votes

Voici un bit de code pour obtenir Expliquer le plan de requête Résultats dans Android Logcat à partir d'une application Android en cours d'exécution. Je commence par un sqliteopenhelper dbhelper et un sqlitequerybuilder qb . xxx

J'ai laissé tomber cela dans mon contentprovider.Query ( ) et maintenant je peux voir exactement comment toutes les requêtes sont effectuées. (Dans mon cas, on dirait que le problème est trop de requêtes plutôt que de mauvaise utilisation de l'indexation; mais peut-être que cela aidera quelqu'un d'autre ...)


0 commentaires

0
votes

Un point mineur pour ajouter à la réponse autrement complète de Robie: le VFS en SQLite (qui est principalement préoccupé par le verrouillage) peut être échangé pour des alternatives. Vous mai trouver l'une des alternatives telles que UNIX-excl (STRAND> ou UNIX-Aucun Pour être plus rapide, mais il a suivi les avertissements sur le Page SQLITE VFS !

normalisation (de structures de table) mérite également d'être envisagée (si vous n'avez pas déjà) simplement parce qu'il a tendance à fournir la plus petite représentation des données dans la base de données; Il s'agit d'un compromis, moins d'E / S pour plus de CPU et une personne qui convient généralement à des bases de données d'entreprise à moyenne échelle (le genre que je connais le plus familier), mais j'ai peur de ne pas avoir aucune idée de si le Le compromis fonctionne bien sur les plates-formes à petite échelle comme Android.


0 commentaires