select_related の sql を見てみる
select_related の sql を見てみる
ORMを雰囲気で使っているので少しずつ理解を深めていきたいと思っている今日この頃です。
select_relatedを使うとデータベースへのアクセス回数を減らせて負荷を軽減できるみたいです。
参考:
select_related()の仕様を理解する
Django ORM の SQL を出力する方法まとめ
モデル
モデルは下の通り。
from django.db import models
class Writer(models.Model):
name = models.CharField(max_length=128)
class Article(models.Model):
writer = models.ForeignKey(Writer, on_delete=models.CASCADE , related_name='articles')
title = models.CharField(max_length=512)
contents = models.TextField()
データベース
データは下の通り。
MariaDB [djangodatabase]> select * from myapp_writer;
+----+-----------+
| id | name |
+----+-----------+
| 1 | satoh |
| 2 | suzuki |
| 3 | takahashi |
+----+-----------+
MariaDB [djangodatabase]> select * from myapp_article;
+----+--------+------------------------+-----------+
| id | title | contents | writer_id |
+----+--------+------------------------+-----------+
| 1 | java | java for beginner | 1 |
| 2 | python | python for beginner | 1 |
| 3 | R | R for datascientist | 2 |
| 4 | ruby | practice ruby on rails | 3 |
+----+--------+------------------------+-----------+
プログラム
select_related の構文は下の通りです。
[クラス名].objects.select_related('[foreignKeyのフィールド]').xxx
それでは myapp_article テーブルから myapp_writer テーブルの情報を取得してみたいと思います。
python3.6 manage.py shell
>>> from myapp.models import Writer, Article
>>> data = Article.objects.select_related('writer').get(id=1)
>>> writer = data.writer
>>> writer_name = writer.name
>>> print(writer_name)
satoh
python3.6 manage.py shell
>>> from myapp.models import Writer, Article
>>> data = Article.objects.get(id=1)
>>> writer = data.writer
>>> writer_name = writer.name
>>> print(writer_name)
satoh
これらのコードは同じことをやっているようですが参考のリンクによると、前者はデータベースへのアクセスが1回で後者はデータベースへのアクセスが2回のようです。と言う事で「select_related」のクエリを見てみたいと思います。
>>> query = Article.objects.select_related('writer').query
>>> print(query)
SELECT myapp_article
.id
, myapp_article
.writer_id
, myapp_article
.title
, myapp_article
.contents
, myapp_writer
.id
, myapp_writer
.name
FROM myapp_article
INNER JOIN myapp_writer
ON (myapp_article
.writer_id
= myapp_writer
.id
)
きちんとJOINしているみたいですね。下記の通りに記述すると接続先のテーブルの値を一回取得する事が出来ます。
>>> writer_name = Article.objects.select_related('writer').values('writer__name').get(id=3)
>>> print(writer_name)
{'writer__name': 'suzuki'}
ディスカッション
コメント一覧
まだ、コメントがありません