In the process of optimizing queries in my app I noticed something strange. In a given section of code I would get the object, make update some values and then save. In theory this should execute 2 queries. But in fact its executing 3 queries. 1 select query when I get the object and 2 when I save the object (Another select and then the update!). While removing one query may seem silly. In this particular method I am updating many objects so every query I save is 1 less hit on the db and should speed up the method.
Through inspection of the queries the two select queries are different the first gets many things and the select executed by the same is simple.
Here is the example code:
myobject = room.myobjects.get(id=myobject_id) # one query executed here
myobject.color = color
myobject.shape = shape
myobject.place = place
myobject.save() # two queries executed here
queries:
1) "SELECT `rooms_object`.`id`, `rooms_object`.`room_id`, ......FROM `rooms_object` WHERE (`rooms_object`.`id` = %s AND `rooms_object`.`room_id` = %s )"
2) "SELECT (1) AS `a` FROM `rooms_object` WHERE `rooms_object`.`id` = %s LIMIT 1"
3) "UPDATE ......this ones obvious"
I want the save method to recognize it already has the object in memory and it does not need to get it again….if that is even possible…
The second query is not actually pulling down the object again. It is doing an extremely fast “existence” check on the
idbefore performing anUPDATEquery. All that is returned from that query is a single1, and the field is indexed, so it should be extremely efficient.The reason they have chosen to design the ORM this way, is first they look at your object to see if it currently has an ID. If it does, they do the
SELECTto make sure it really does still exist in the database. If it does, they perform the update. If somehow the record does not exist, they perform anINSERT. You can test this by creating the object, then deleting the row manually from your database, without django knowing. Then callsave()This is how it works to make sure django maintains consistency.
If it were a new object, you would only get a single
INSERTquery, because it knows the object has noidright now.