실전 Django의 모델 조작의prefetchrelated () 조회의 최적화 (2)
여기
1편은 여기서 예와 select 을 강의합니다.related()
제3편은 여기서 몇 가지 실례를 이용하여 복잡한 조회의 최적 실천을 설명한다
3. prefetch_related()
prefetchrelated ()로 최적화합니다.혹시 One Tomany Field라는 게 하나도 없다고 말할지도 몰라요.실제로 ForeignKey는 다대일 필드이고 ForeignKey와 관련된 필드는 다대일 필드입니다.
작용과 방법
prefetch_related() 및 selectrelated()의 디자인 목적은 매우 비슷하다. 모두 SQL 조회의 수를 줄이기 위한 것이지만 실현 방식은 다르다.후자는 JOIN 문을 통해 SQL 쿼리 내에서 문제를 해결합니다.그러나 다대다 관계에 대해 SQL 문구를 사용하여 해결하는 것은 현명하지 않다. JOIN이 얻은 표가 길기 때문에 SQL 문구의 운행 시간이 증가하고 메모리가 차지하는 시간이 증가하기 때문이다.n개의 객체가 있는 경우 각 객체의 여러 쌍 다중 필드가 Mi 막대에 해당합니다.Σ(n) Mi 행의 결과 테이블.
prefetch_related () 의 해결 방법은 각각의 표를 조회한 다음 파이톤으로 그들 사이의 관계를 처리하는 것이다.계속해서 상기 예시를 설명하자면, 만약에 우리가 장삼이 가 본 모든 도시를 얻으려면prefetchrelated () 는 다음과 같이 해야 합니다.
-
>>> zhangs = Person.objects.prefetch_related(
'visitation').get(firstname=
u" ",lastname=
u" ")
-
>>>
for city
in zhangs.visitation.all() :
-
...
print city
-
...
SQL :
-
SELECT
`QSOptimize_person`.
`id`,
`QSOptimize_person`.
`firstname`,
-
`QSOptimize_person`.
`lastname`,
`QSOptimize_person`.
`hometown_id`,
`QSOptimize_person`.
`living_id`
-
FROM
`QSOptimize_person`
-
WHERE (
`QSOptimize_person`.
`lastname` =
' '
AND
`QSOptimize_person`.
`firstname` =
' ');
-
-
SELECT (
`QSOptimize_person_visitation`.
`person_id`)
AS
`_prefetch_related_val`,
`QSOptimize_city`.
`id`,
-
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
-
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE
`QSOptimize_person_visitation`.
`person_id`
IN (
1);
SQL Person , , `QSOptimize_person_visitation` `person_id` , `city` (INNER JOIN ) 。
+----+-----------+----------+-------------+-----------+
| id | firstname | lastname | hometown_id | living_id |
+----+-----------+----------+-------------+-----------+
| 1 | | | 3 | 1 |
+----+-----------+----------+-------------+-----------+
1 row in set (0.00 sec)
±----------------------±—±----------±------------+
| _prefetch_related_val | id | name | province_id |
±----------------------±—±----------±------------+
| 1 | 1 | | 1 |
| 1 | 2 | | 2 |
| 1 | 3 | | 1 |
±----------------------±—±----------±------------+
3 rows in set (0.00 sec) 、 、 。
, , :
>>> hb = Province.objects.prefetch_related('city_set').get(name__iexact=u" ")
>>> for city in hb.city_set.all():
... city.name
...
SQL :
SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
FROM `QSOptimize_province`
WHERE `QSOptimize_province`.`name` LIKE ' ' ;
SELECT QSOptimize_city
. id
, QSOptimize_city
. name
, QSOptimize_city
. province_id
FROM QSOptimize_city
WHERE QSOptimize_city
. province_id
IN (1); 획득한 표:
+----±----------+
| id | name |
+----±----------+
| 1 | |
+----±----------+
1 row in set (0.00 sec)
+----±----------±------------+ | id | name | province_id | +--±------------±--------------------+| 1 | 우한시| 1 | 3 | 텐언시| 1 | +------------------------------+2 rows in set(0.00sec)
우리는 prefetch가 사용하는 것이 IN 문장으로 이루어진 것을 볼 수 있다.이렇게 하면QuerySet에 있는 대상의 수가 너무 많을 때 데이터베이스 특성에 따라 성능 문제가 발생할 수 있습니다.
사용법
*lookups 매개 변수
prefetch_related () 는 Django < 1.7 에서 이 방법만 사용합니다.및 selectrelated () 와 같이prefetchrelated () 도 깊이 있는 검색을 지원합니다. 예를 들어 장씨 성을 가진 모든 사람이 갔던 성을 얻으려면:
-
>>> zhangs = Person.objects.prefetch_related(
'visitation__province').filter(firstname__iexact=
u' ')
-
>>>
for i
in zhangs:
-
...
for city
in i.visitation.all():
-
...
print city.province
-
...
SQL:
-
SELECT
`QSOptimize_person`.
`id`,
`QSOptimize_person`.
`firstname`,
-
`QSOptimize_person`.
`lastname`,
`QSOptimize_person`.
`hometown_id`,
`QSOptimize_person`.
`living_id`
-
FROM
`QSOptimize_person`
-
WHERE
`QSOptimize_person`.
`firstname`
LIKE
' ' ;
-
-
SELECT (
`QSOptimize_person_visitation`.
`person_id`)
AS
`_prefetch_related_val`,
`QSOptimize_city`.
`id`,
-
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE
`QSOptimize_person_visitation`.
`person_id`
IN (
1,
4);
-
-
SELECT
`QSOptimize_province`.
`id`,
`QSOptimize_province`.
`name`
-
FROM
`QSOptimize_province`
-
WHERE
`QSOptimize_province`.
`id`
IN (
1,
2);
:
+----+-----------+----------+-------------+-----------+
| id | firstname | lastname | hometown_id | living_id |
+----+-----------+----------+-------------+-----------+
| 1 | | | 3 | 1 |
| 4 | | | 2 | 2 |
+----+-----------+----------+-------------+-----------+
2 rows in set (0.00 sec)
±----------------------±—±----------±------------+
| _prefetch_related_val | id | name | province_id |
±----------------------±—±----------±------------+
| 1 | 1 | | 1 |
| 1 | 2 | | 2 |
| 4 | 2 | | 2 |
| 1 | 3 | | 1 |
±----------------------±—±----------±------------+
4 rows in set (0.00 sec)
±—±----------+
| id | name |
±—±----------+
| 1 | |
| 2 | |
±—±----------+
2 rows in set (0.00 sec)
, prefetch_related , 1.7 select_related 。
, QuerySet , , prefetch_related 。 Django , 。 filter()、exclude() SQL 。 all() , 。
, “ ” , SQL :
-
plist = Person.objects.prefetch_related(
'visitation')
-
[p.visitation.filter(name__icontains=
u" ")
for p
in plist]
4 , 2+4 SQL :
-
SELECT
`QSOptimize_person`.
`id`,
`QSOptimize_person`.
`firstname`,
`QSOptimize_person`.
`lastname`,
-
`QSOptimize_person`.
`hometown_id`,
`QSOptimize_person`.
`living_id`
-
FROM
`QSOptimize_person`;
-
-
SELECT (
`QSOptimize_person_visitation`.
`person_id`)
AS
`_prefetch_related_val`,
`QSOptimize_city`.
`id`,
-
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
-
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE
`QSOptimize_person_visitation`.
`person_id`
IN (
1,
2,
3,
4);
-
-
SELECT
`QSOptimize_city`.
`id`,
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
-
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE(
`QSOptimize_person_visitation`.
`person_id` =
1
AND
`QSOptimize_city`.
`name`
LIKE
'% %' );
-
-
SELECT
`QSOptimize_city`.
`id`,
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
-
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE (
`QSOptimize_person_visitation`.
`person_id` =
2
AND
`QSOptimize_city`.
`name`
LIKE
'% %' );
-
-
SELECT
`QSOptimize_city`.
`id`,
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
-
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE (
`QSOptimize_person_visitation`.
`person_id` =
3
AND
`QSOptimize_city`.
`name`
LIKE
'% %' );
-
-
SELECT
`QSOptimize_city`.
`id`,
`QSOptimize_city`.
`name`,
`QSOptimize_city`.
`province_id`
-
FROM
`QSOptimize_city`
-
INNER
JOIN
`QSOptimize_person_visitation`
ON (
`QSOptimize_city`.
`id` =
`QSOptimize_person_visitation`.
`city_id`)
-
WHERE (
`QSOptimize_person_visitation`.
`person_id` =
4
AND
`QSOptimize_city`.
`name`
LIKE
'% %' );
-
。
,QuerySet lazy , 。 Python ,for plist iterator, 。 SQL prefetch_related 。
city , Person.visitation filter , 。 , SQL 。
? Django >= 1.7, Prefetch , Django < 1.7, Python 。
-
plist = Person.objects.prefetch_related(
'visitation')
-
[[city
for city
in p.visitation.all()
if
u" "
in city.name]
for p
in plist]
Prefetch
Django >= 1.7, Prefetch prefetch_related 。
: 1.7 Django , Django , 。
Prefetch :
- Prefetch prefetch 。
- Prefetch prefetch_related , 。
- queryset prefetch QuerySet。
- to_attr prefetch 。
- Prefetch lookups 。
, “ ” “ ” :
-
wus = City.objects.filter(name__icontains =
u" ")
-
zhous = City.objects.filter(name__icontains =
u" ")
-
plist = Person.objects.prefetch_related(
-
Prefetch(
'visitation', queryset = wus, to_attr =
"wu_city"),
-
Prefetch(
'visitation', queryset = zhous, to_attr =
"zhou_city"),)
-
[p.wu_city
for p
in plist]
-
[p.zhou_city
for p
in plist]
: , 。
,Prefetch 。
None
None prefetch_related。 :
>>> prefetch_cleared_qset = qset.prefetch_related(None)
- prefetch_related 。
- prefetch_related , Python 。
- select_related 。 select_related 。
- Django >= 1.7 Prefetch , Django 。
- prefetch_related ,Prefetch 。
- prefetch_related prefetch , , 。
- None prefetch_related。
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Django 라우팅 계층 URLconf 작용 및 원리 해석URL 구성(URLconf)은 Django가 지원하는 웹 사이트의 디렉토리와 같습니다.그것의 본질은 URL과 이 URL을 호출할 보기 함수 사이의 맵표입니다. 위의 예제에서는 URL의 값을 캡처하고 위치 매개 변수로...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.