Expérience de synchronisation d'évaluation des ensembles de requêtes Django

Délais d'évaluation de l'ensemble de requêtes Django http://djangoproject.jp/doc/ja/1.0/ref/models/querysets.html

Nous vérifierons lors de l'émission de SQL.

** Préparation **

environnement: Python 2.7.10 Django 1.9.7 MySQL 5.6.30

Les données: Créez un cours de gestion de livres simple de manière appropriée

mysql> select * from book_book;
+----+------+-------------+-----+----------------------------+----------------------------+
| id | name | description | tag | created_at                 | updated_at                 |
+----+------+-------------+-----+----------------------------+----------------------------+
|  1 | A    | A's book    | A   | 2016-06-22 01:50:25.895551 | 2016-06-22 01:50:25.895986 |
|  2 | B    | B's book    | B   | 2016-06-22 01:50:36.743094 | 2016-06-22 01:50:36.743139 |
|  3 | C    | C's book    | C   | 2016-06-22 01:50:46.279098 | 2016-06-22 01:50:46.279141 |
|  4 | D    | D's book    | D   | 2016-06-22 01:50:56.831194 | 2016-06-22 01:50:56.831237 |
|  5 | E    | E's book    | E   | 2016-06-22 01:51:06.663500 | 2016-06-22 01:51:06.663562 |
+----+------+-------------+-----+----------------------------+----------------------------+
5 rows in set (0.00 sec)

Afficher le SQL d'émission:

settings.py


LOGGING = {
    'version': 1,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },

    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'handlers': ['console'],
        },
    }
}

** Entraine toi **

Commençons par comprendre.

>>> query = Book.objects.get(id=1)
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)

Quand je l'ai obtenu avec get, SQL a été émis soudainement. c'est,

>>> type(query)
<class 'book.models.Book'>

Parce qu'il est récupéré par un objet, pas par un ensemble de requêtes.

Si vous changez ceci pour filtrer

>>> query = Book.objects.filter(id=1)
>>> type(query)
<class 'django.db.models.query.QuerySet'>

Il est récupéré par l'ensemble de requêtes et SQL n'est pas émis à ce stade. Suivez ce document pour effectuer chaque opération.

** Itération **

>>> for book in query:
...   print book
... 
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
Book object

tranche

>>> query[:1]
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1 LIMIT 1; args=(1,)
[<Book: Book object>]

repr

>>> repr(query)
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1 LIMIT 21; args=(1,)
'[<Book: Book object>]'

len

>>> len(query)
(0.004) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
1

list

>>> list(query)
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]

Comme indiqué, chaque opération a évalué l'ensemble de requêtes et émis du code SQL.

** cache **

Un ensemble de requêtes qui a été évalué une fois est mis en cache et aucun SQL n'est émis même si l'opération est à nouveau évaluée.

>>> query = Book.objects.filter(id=1)
>>> list(query)
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]
>>> list(query)
[<Book: Book object>]
>>> list(query)
[<Book: Book object>]
>>> query[:1]
[<Book: Book object>]
>>> len(query)
1

Notez que c'est l'ensemble de requêtes qui est mis en cache ici, pas le SQL.

>>> #Les résultats de l'évaluation de l'ensemble de requêtes sont mis en cache
>>> for i in xrange(1, 5):
...   list(query)
... 
[<Book: Book object>]
[<Book: Book object>]
[<Book: Book object>]
[<Book: Book object>]
[<Book: Book object>]
>>> #Les résultats SQL eux-mêmes ne sont pas mis en cache
>>> for i in xrange(1, 5):
...   list(Book.objects.filter(id=1))
... 
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]
(0.002) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]
(0.002) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)

De plus, les conditions ajoutées à l'ensemble de requêtes ne sont pas mises en cache. (Parce que l'exemple ci-dessous est équivalent à Book.objects.filter (id = 1) .order_by ('id'))

>>> query.order_by('id')
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1 ORDER BY `book_book`.`id` ASC LIMIT 21; args=(1,)
[<Book: Book object>]
>>> query.order_by('id')
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1 ORDER BY `book_book`.`id` ASC LIMIT 21; args=(1,)
[<Book: Book object>]

Dans ce cas, il sera mis en cache comme suit.

>>> query2 = query.order_by('id')
>>> list(query2)
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1 ORDER BY `book_book`.`id` ASC; args=(1,)
[<Book: Book object>]
>>> list(query2)
[<Book: Book object>]

Étant donné que le SQL émis change même dans l'ordre suivant, il semble que chacun soit évalué individuellement.

>>> query = Book.objects.filter(id=1)
>>> query[:1]
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1 LIMIT 1; args=(1,)
[<Book: Book object>]
>>> list(query)
(0.001) SELECT `book_book`.`id`, `book_book`.`name`, `book_book`.`description`, `book_book`.`tag`, `book_book`.`created_at`, `book_book`.`updated_at` FROM `book_book` WHERE `book_book`.`id` = 1; args=(1,)
[<Book: Book object>]

En effet, lorsque la requête [: 1] est définie en premier, la limite 1 est ajoutée à la requête de Book.objects.filter (id = 1). Cependant, si vous interrogez [: 1] après la liste (requête), le cache fonctionnera car vous obtiendrez une tranche de liste (requête).

Recommended Posts

Expérience de synchronisation d'évaluation des ensembles de requêtes Django
Django "Query Set, Object has no attribute'foo '" solution