Thread: [SQLObject] One to 'a lot' relationship
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Robert L. <ro...@le...> - 2004-08-28 23:29:49
|
What is the best (read fastest) way to handle a 1-many relationship in SQLObject where the many is thousands of rows? The current 0.5.2 release issues an individual select for every row on the many side, which is a significant bottleneck. Is the SVN version better in this regard or do I need to code up something specific for this situation? If SVN is the way to go, is there a specific upgrade strategy I need to follow or can I just uninstall 0.5.2 and install the SVN version w/o requiring db changes? Robert [so many questions, so few answers:-(] |
From: Ian B. <ia...@co...> - 2004-08-29 00:21:33
|
Robert Leftwich wrote: > What is the best (read fastest) way to handle a 1-many relationship in > SQLObject where the many is thousands of rows? The current 0.5.2 release > issues an individual select for every row on the many side, which is a > significant bottleneck. Is the SVN version better in this regard or do I > need to code up something specific for this situation? If SVN is the way > to go, is there a specific upgrade strategy I need to follow or can I > just uninstall 0.5.2 and install the SVN version w/o requiring db changes? SVN is significantly better, though I actually thought 0.5.2 also did this properly. Anyway, it's supposed to fetch all the columns on any select. There's no database changes necessary to upgrade, but the main module has changed names from SQLObject to sqlobject, and MyClass(id) is now MyClass.get(id), and MyClass.new(**kw) is now MyClass(**kw). -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Robert L. <ro...@le...> - 2004-08-29 02:20:20
|
(oops, did not send to the list, apologies for the direct email Ian) Ian Bicking wrote: > > SVN is significantly better, though I actually thought 0.5.2 also did > this properly. Anyway, it's supposed to fetch all the columns on any > select. > > There's no database changes necessary to upgrade, but the main module > has changed names from SQLObject to sqlobject, and MyClass(id) is now > MyClass.get(id), and MyClass.new(**kw) is now MyClass(**kw). > To add to the list of changes: The connection logic is deprecated, e.g. you now need to use : from sqlobject.postgres import builder; PostgresConnection = builder(); conn = PostgresConnection(...) or connectionForURI("postgres://...") I'm using the former as I can't seem to get the latter to work atm. The names of the MultipleJoin properties now have an 's' appended to them (I'm not sure if they are fully pluralised, i.e. is address now addresses?). Also the capitalisation seems to have changed so that for a joined table ABCUnit the property is now aBCUnits instead of the old abcUnit - this seems a little counter intuitive, is it possible to revert back or select the old naming scheme in some way. In addition the rev206 SVN release still issues individual selects for every row in the joined table, e.g. It will issue : SELECT id FROM address WHERE person_id = 299 and then for every returned id it will issue: SELECT * FROM address WHERE id = 488 ... (3500 times) where * is the name of every column in the address table. The culprit seems to be class FileConnection(DBConnection): ... def _SO_selectJoin(self, soClass, column, value): results = [] # @@: seems lame I need to do this... value = int(value) for id in self._allIDs(soClass._table): d = self._fetchDict(soClass._table, id) if d[column] == value: results.append((id,)) return results which overrides the default _SO_selectJoin in DBConnection. Am I doing something wrong? Robert |
From: Charles B. <li...@st...> - 2004-08-29 15:32:37
|
Hi, I've been revisiting the concept of connections and caching in SQLObject to get a few of the nuances straight in my head. In the process I tried to jot these concepts down in writing and posted them on the SQLObject Wiki site here: http://wiki.sqlobject.org/connections.html This process lead me to two big questions on the topic: 1. Is there a way to manually close a connection? 2. Is there a way to manually expire the cache of a connection? In a prior mailing list thread I think I read that objects are not coupled with connections, so maybe question 2 is worded incorrectly. (this is specifically asked with the method of passing a connection to a object in mind). On a more general note I'd be very interested to hear details on how others deal with connections in their SQLObject applications, especially multi-process applications. Thanks in advance, -Charles. |
From: Ian B. <ia...@co...> - 2004-08-31 03:39:34
|
Charles Brandt wrote: > Hi, > > I've been revisiting the concept of connections and caching in SQLObject to > get a few of the nuances straight in my head. In the process I tried to jot > these concepts down in writing and posted them on the SQLObject Wiki site > here: > http://wiki.sqlobject.org/connections.html > > This process lead me to two big questions on the topic: > > 1. Is there a way to manually close a connection? Hmm... no. And since SQLObject does pooling it's not trivial. > 2. Is there a way to manually expire the cache of a connection? connection.cache.expireAll() -- that won't removed the cached objects, but it will only hold weak references. > In a prior mailing list thread I think I read that objects are not coupled > with connections, so maybe question 2 is worded incorrectly. (this is > specifically asked with the method of passing a connection to a object in > mind). They are coupled rather strongly to connections. > On a more general note I'd be very interested to hear details on how others > deal with connections in their SQLObject applications, especially > multi-process applications. Yes, that's still a bit of an open issue. It's hard, because it really depends on how accurate you want to be -- you can be very accurate by checking each time an attribute is accessed, but that's really inefficient, and may give you an inconsistent view. I'd be interested in hearing other people's thoughts as well. -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Charles B. <li...@st...> - 2004-08-31 22:30:29
|
> > 1. Is there a way to manually close a connection? > > Hmm... no. And since SQLObject does pooling it's not trivial. I'm more interested in removing and closing connection objects themselves (i.e. all connections in a specific connection object's pool) vs a single specific connection in a connection object's pool. This would be especially useful when the connection object is only passed into objects when they are fetched (vs defined in the object definition). When I use connection objects this way, they are effectively a pool of one connection used for fetching/updating one object. Granted this is not as efficient as keeping a pool of connections (or a connection per thread) but it is handy for a quick test or rare use situations. (even then it is impractical without a close function though). I'm not sure if looking at this higher level would simplify the problem to a more trival one. My work around is to re-use connections as intended. :) > > 2. Is there a way to manually expire the cache of a connection? > > connection.cache.expireAll() -- that won't removed the cached objects, > but it will only hold weak references. I think cache in "connection.cache.expireAll()" is actually a CacheSet object, and expireAll() is a method of CacheFactory. That lead me to try the following: for key in connection.cache.caches.keys(): connection.cache.caches[key].expireAll() but got: File "/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site -packages/SQLObject/Cache.py", line 151, in expireAll self.expiredCache[key] = ref(obj) NameError: global name 'obj' is not defined should obj in this case actually be value from the previous line of: for key, value in self.cache.items(): ? I can file a bug report if so. In the mean time I'm giving the method posted by Eddie Corns in July a closer look: http://thread.gmane.org/gmane.comp.python.sqlobject/1630 > > On a more general note I'd be very interested to hear details on how others > > deal with connections in their SQLObject applications, especially > > multi-process applications. > > Yes, that's still a bit of an open issue. It's hard, because it really > depends on how accurate you want to be -- you can be very accurate by > checking each time an attribute is accessed, but that's really > inefficient, and may give you an inconsistent view. I'd be interested > in hearing other people's thoughts as well. My goal with these questions is to end up with an approach that caches fetched data for a specific page request, and then flushes the cache at the end of the request. In practice this might not save much over checking the database each time, but its the best compromise I've come up with so far. Thanks Ian! -Charles. |
From: Michael W. <li...@mi...> - 2004-09-02 07:48:56
|
> I think cache in "connection.cache.expireAll()" is actually a CacheSet > object, and expireAll() is a method of CacheFactory. That lead me to t= ry > the following: > > for key in connection.cache.caches.keys(): > connection.cache.caches[key].expireAll() Hmnn... that's almost exactly what I have done. import gc def expire_all(): c =3D get_connection() for k in c.cache.caches.keys(): c.cache.caches[k].expireAll() gc.collect() Ah, thought this looked familiar: "The SQLObject code has a bug in expireAll =96 ref(obj) instead of ref(value) =96 and the method isn=92t called from anywhere in the code ei= ther, at least not in the svn checkout I am looking at." http://mikewatkins.net/categories/technical/2004-07-14-1.html |