OneToOneFieldの裏側で発行されているSQLを確認する

この記事は(第157回)Python mini Hack-a-thon(ハイブリッド) の記事です。

先週、こちらの記事を投稿したところ、先輩からアドバイスをもらいました。

確かにSQLを出力せずに調べていた(その前段階で「?」だった)事もあったので、今回は出力してみることにします。

SQLの出力方法

いつもながら自走プログラマーの内容を参考に、settings.pyに記述します。設定内容はリンク先に記述されているので割愛します。

60:Django ORMでどんなSQLが発行されているか気にしよう

動かしてみる

まずはUserを取得してみます。

まず、結果は通常のauth.Userを利用しているので予想通り、auth_userを普通に取得した、と言う内容でした。

>>> nibu = User.objects.get(username="nibu")
(0.001) SELECT "auth_user"."id", 
              "auth_user"."password", 
              "auth_user"."last_login", 
              "auth_user"."is_superuser", 
              "auth_user"."username", 
              "auth_user"."first_name", 
              "auth_user"."last_name", 
              "auth_user"."email", 
              "auth_user"."is_staff", 
              "auth_user"."is_active", 
              "auth_user"."date_joined" 
       FROM "auth_user" 
       WHERE "auth_user"."username" = 'nibu' 
       LIMIT 21; 
args=('nibu',); alias=default

次に、more についても調べてみます。 こちらも予想通りでした。

※前回の記事の動画のコードを元にしたので、drivers_moreになっています。

>>> nibu_more = More.objects.get(user=nibu)
(0.000) SELECT "drivers_more"."id", 
              "drivers_more"."user_id", 
              "drivers_more"."address", 
              "drivers_more"."postal_code" 
       FROM "drivers_more" 
       WHERE "drivers_more"."user_id" = 1 
       LIMIT 21; 
args=(1,); alias=default

この次、nibu.moreだと自分の想定とはちょっと異なりました。 JOINではなく、drivers_moreを呼び出した状態になっています。

自分のイメージは結合しているのかな?と思っていましたが、SQL的には結合せず効率の良いものが発行されていたことがわかります。

>>> nibu.more
(0.000) SELECT "drivers_more"."id", 
              "drivers_more"."user_id", 
              "drivers_more"."address", 
              "drivers_more"."postal_code" 
       FROM "drivers_more" 
       WHERE "drivers_more"."user_id" = 1 
       LIMIT 21; 
args=(1,); alias=default
<More: More object (1)>

となると、nibu_moreからuserを参照した場合も同様かな?と思ったところ、同様でした。

>>> nibu_more.user
(0.002) SELECT "auth_user"."id", 
              "auth_user"."password", 
              "auth_user"."last_login", 
              "auth_user"."is_superuser", 
              "auth_user"."username", 
              "auth_user"."first_name", 
              "auth_user"."last_name", 
              "auth_user"."email", 
              "auth_user"."is_staff", 
              "auth_user"."is_active", 
              "auth_user"."date_joined" 
       FROM "auth_user" 
       WHERE "auth_user"."id" = 1 
       LIMIT 21; 
args=(1,); alias=default
<User: nibu>

というわけで、どんなSQLが発行されているかを確認するのは大事だなと再認識しました。

もうちょっと複雑だったり、初めてみるQuerySet APIを利用したものはSQLを確認しようとしていましたが、こういう所から1つずつ意識していこうと思います。