2010-06-16 9 views
2

J'ai ce genre d'entité:Comment regrouper efficacement les recherches d'index?

  • Molecule
  • Atom
  • MoleculeAtom

Compte tenu d'une list(molecule_ids) dont les longueurs est dans les centaines, je dois obtenir un dict de la forme {molecule_id: list(atom_ids)}. De même, étant donné un list(atom_ids) dont la longueur est dans les hunreds, je dois obtenir un dict de la forme {atom_id: list(molecule_ids)}.

Ces deux recherches en masse doivent se dérouler très rapidement. En ce moment je fais quelque chose comme:

atom_ids_by_molecule_id = {} 

for molecule_id in molecule_ids: 
    moleculeatoms = MoleculeAtom.all().filter('molecule =', db.Key.from_path('molecule', molecule_id)).fetch(1000) 
    atom_ids_by_molecule_id[molecule_id] = [ 
     MoleculeAtom.atom.get_value_for_datastore(ma).id() for ma in moleculeatoms 
    ] 

Comme je l'ai dit, len(molecule_ids) est dans les centaines. J'ai besoin de faire ce genre de recherche d'index en vrac sur presque chaque requête, et j'ai besoin d'être rapide, et maintenant c'est trop lent.

Idées:

  • Est-ce que l'aide d'un Molecule.atomsListProperty faire ce que je dois? Considérez que je stocke des données supplémentaires sur le noeud MoleculeAtom, et rappelez-vous qu'il est tout aussi important pour moi de faire la recherche dans les directions molécule-> atome et atome-> molécule.

  • Mise en cache? J'ai essayé de mémoriser des listes d'identifiants d'atome codés par l'ID de molécule, mais j'ai des tonnes d'atomes et de molécules, et le cache ne peut pas y entrer. Que diriez-vous de dénormaliser les données en créant un nouveau type d'entité dont le nom de clé est un ID de molécule et dont la valeur est une liste d'ID d'atome? L'idée est, en appelant db.get sur 500 touches est probablement plus rapide que de boucler à travers 500 fetchs avec des filtres, non?

+0

Cela ressemble beaucoup à un problème où l'utilisation d'une base de données (avec des données dénormalisées) fonctionnerait mieux. Parce que cela évoluera mieux et que les bases de données sont intrinsèquement conçues pour gérer les jointures de données de la manière la plus efficace possible. –

Répondre

3

Votre troisième approche (dénormalisation des données) est, en général, la bonne. En particulier, db.get par les clés est en effet à peu près aussi rapide que le magasin de données. Bien sûr, vous devrez également dénormaliser l'inverse (entité avec un nom d'atome clé ID, valeur une liste d'ID de molécule) et devrez tout mettre à jour attentivement lorsque des atomes ou des molécules sont modifiés, ajoutés ou supprimé - si vous avez besoin d'être transactionnel (plusieurs de ces modifications étant potentiellement en jeu en même temps) vous devez arranger les relations ancêtres .. mais je ne vois pas comment le faire pour les deux molécules et atomes au en même temps, alors peut-être que cela pourrait être un problème. Peut-être, si les modifications sont assez rares (et en fonction d'autres aspects de votre application), vous pourriez sérialiser les modifications dans les tâches en file d'attente.