On Nov 7, 2009, at 6:03 PM, Adam Dziendziel wrote:
> > Hi, > > I am trying to use the query caching solution described here: > http://svn.sqlalchemy.org/sqlalchemy/trunk/examples/query_caching/per_session.py > > In most cases it works, the returned records are cached, I store them > in a LRU cache modeled after http://code.activestate.com/recipes/498245/ > > However, when I run a long running operation, which operates on > hundreds of other records, apparently the garbage collection is run on > the session's weak-referencing identity map. The cache keeps the > returned records, but other eagerly loaded related instances of the > returned records are lost. that's not possible, since those records are strongly referenced by their cached parents (see below), which in turn are strongly referenced by the cache. The GC will only collect items that have a strong reference count of zero. > The ORM issues queries to load them again > from the database. I understand that there are no strong references > between an instance and other related instances. Assuming you are not using "dynamic" loaders, that's not correct. When a collection or attribute is "eagerly loaded", it is placed within the parent's __dict__ during the load operation. Similarly for "lazy loads", once the lazily loading attribute is referenced, the then loaded collection or attribute is placed in the parent's __dict__. In this case it sounds more like the parents have collections or attributes which are to be lazily loaded upon first access, so the link between parent/child hasn't yet been established. In the case of a many-to-one, you can say "parent.child" and not see any SQL, even though the "lazy load" operation was invoked, because a simple identity lookup is performed in the session. > > What is the best solution to keep related instances in a session? sounds like you need to ensure your eager loads are working properly (or another use my other suggestion below). > > If I create a session with weak_identity_map=False, then during my > long running operation I will run out of memory, unless I expunge > unused records, however, it is easy to miss one record and the > identity map will be growing anyway. I recommend against using that option since we're trying to decide if we should just drop it across the board, its pretty legacy. > > Is there possible to get a list of referenced instances of another > instance, so that I could store the list together with the instance in > the MRU cache? What I usually do when i want to ensure what gets cached (since im usually serializing into memcached), and i dont want to worry what the particular eager loading configuration is, is to make a method like "full_load()" which ensures all the important attributes and collections are present. this will issue lazy loads for anything that wasn't already loaded: def full_load(self): self.collection1 self.some_reference return self However, if you are truly eager loading all of those attributes then this step is unnecessary. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---