Is it possible to use a couple of fields not from the primary key to retrieve items (already fetched earlier) from the identity map? For example, I often query a table by (external_id, platform_id)
pair, which is a unique key, but not a primary key. And I want to omit unnecessary SQL queries in such cases.
An identity map is kept for a lifecycle of a SQLAlchemy's session
object i.e. in case of a web-service or a RESTful api the session
object's lifecycle is not more than a single request
(recommended).
From : http://martinfowler.com/eaaCatalog/identityMap.html
An Identity Map keeps a record of all objects that have been read from the database in a single business transaction. Whenever you want an object, you check the Identity Map first to see if you already have it.
In SQLAlchemy's ORM there's this special query method get()
, it first looks into identity_map
using the pk (only allowed argument) and returns object from the identity map, actually executing the SQL
query and hitting the database.
From the docs:
get(ident)
Return an instance based on the given primary key identifier, or
None
if not found.
get()
is special in that it provides direct access to the identity map of the owningSession
. If the given primary key identifier is present in the local identity map, the object is returned directly from this collection and no SQL is emitted, unless the object has been marked fully expired. If not present, a SELECT is performed in order to locate the object.
get()
is using the identity_map
- official docs:It’s somewhat used as a cache, in that it implements the
identity map
pattern, and stores objects keyed to theirprimary key
. However, it doesn’t do any kind of query caching. This means, if you saysession.query(Foo).filter_by(name='bar')
, even ifFoo(name='bar')
is right there, in the identity map, the session has no idea about that. It has to issue SQL to the database, get the rows back, and then when it sees the primary key in the row, then it can look in the local identity map and see that the object is already there. It’s only when you sayquery.get({some primary key})
that the Session doesn’t have to issue a query.
P.S. If you're querying not using pk
, you aren't hitting the identity_map
in the first place.
Few relevant SO questions, helpful to clear the concept: