2

アプリでクエリを最適化する過程で、何か奇妙なことに気づきました。コードの特定のセクションで、オブジェクトを取得し、いくつかの値を更新してから保存します。理論的には、これは2つのクエリを実行する必要があります。しかし実際には、3つのクエリを実行しています。1オブジェクトを取得するときにクエリを選択し、2オブジェクトを保存するときにクエリを選択します(別の選択してから更新します!)。1つのクエリを削除している間、ばかげているように見えるかもしれません。この特定のメソッドでは、多くのオブジェクトを更新しているので、保存するすべてのクエリはデータベースでのヒットが1つ少なくなり、メソッドを高速化するはずです。

クエリの検査を通じて、2つのselectクエリは異なり、最初のクエリは多くのものを取得し、同じものによって実行されるselectは単純です。

サンプルコードは次のとおりです。

            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

クエリ:

   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"

saveメソッドに、オブジェクトがすでにメモリ内にあることを認識させたいので、再度取得する必要はありません。

4

2 に答える 2

6

2番目のクエリは、実際にはオブジェクトを再度プルダウンしていません。idクエリを実行する前に、非常に高速な「存在」チェックを実行していUPDATEます。そのクエリから返されるのは単一1であり、フィールドにはインデックスが付けられているため、非常に効率的です。

彼らがこの方法でORMを設計することを選択した理由は、最初にオブジェクトを調べて、現在IDを持っているかどうかを確認するためです。もしそうなら、彼らはSELECTそれが本当にデータベースにまだ存在していることを確認するために行います。含まれている場合は、更新を実行します。どういうわけかレコードが存在しない場合、それらはを実行しINSERTます。これをテストするには、オブジェクトを作成してから、djangoが知らないうちに、データベースから手動で行を削除します。次に電話save()

これが、djangoが一貫性を維持するための仕組みです。

それが新しいオブジェクトである場合INSERT、オブジェクトには現在存在しないことがわかっているため、クエリは1つしか取得できませんid

于 2012-08-24T22:28:19.923 に答える
3

これは、のforce_updateパラメータで管理されます

Model.save([force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None])

force_updateをTrueに設定して、存在チェックを無効にします( "SELECT(1)AS aFROM ...")。

https://docs.djangoproject.com/en/dev/ref/models/instances/

于 2013-08-09T16:49:51.283 に答える