2011-02-28 4 views
2

에와 쿼리를 최적화하는 것이 가능 쿼리의장고 루프

for student in Student.objects.all(): 
    for course in student.course_set.all(): 
     for grade in course.grade_set.filter(student=student): 
      # do stuff 

양처럼 뭔가에 너무 많은 쿼리를 실행하지 장고를 최적화하는 것은 학생들이 * 코스 * 학년이되는 큰 얻을 수있다.

* 편집 로즈마리의 블로그에서 아이디어를 얻은 후 한 가지 가능성이 있습니다. 스 니펫입니다 만, 기본적으로 내가 (성적) 성적 관심의 마지막 항목에 대한 루프 하나와 루프에 대한 대체

for grade in student.grade_set.order_by('course', 'marking_period').select_related(): 
    if grade.marking_period_id in some_report_input: 
     # do stuff 

내가 (학생, 과정, 표시 기간) 필요한 모든에 대한 참조를 가지고있다. grade.marking_period (다른 쿼리 수행) 대신 marking_period_id와 같은 것을 사용하는 것이 중요했습니다.

트레이드 오프는 코드 가독성입니다. 나는 성적을 걸러 내고 기준에 따라 조직하고 싶었다. 이것은 사소한 것에서 복잡한 것에 이릅니다.

이것은 일반적인 해결책이 아닙니다. 이것이 도움이되지 않을 때가있을 것이라고 확신합니다. 당신이 더 나은 방법을 알고 있다면 의견을 말하십시오.

또 다른 예 : 학생은 과정에 등록됩니다

for student in students: 
    print student 
    for department in departments: 
    print department 
    failed_grades = Grade.objects.filter(course__department=department,course__courseenrollment__user=student,grade__lte=70) 
     for failed_grade in failed_grades: 
     print grade.course 
     print grade.grade 

. 코스에는학과가 있습니다.

+0

여기에 모델을 추가하면 서로 어떻게 연결되는지 이해할 수 있습니다. – marianobianchi

답변

-1

select_related()를 사용할 수 있으며 데이터베이스에 한 번만 도달합니다.

이 링크에서

상세 정보 (장고의 설명서) http://docs.djangoproject.com/en/1.2/ref/models/querysets/#select-related

당신이 당신의 모델 코드를 게시 할 경우 도움이 될 것입니다 귀하의 경우

for x in Student.objects.select_related(): 
    do stuff with x.course.grade` 
+0

아니요. 역관계와 함께 작동하지 않습니다. –

+0

Django 1.2에서 select_related는 역방향 관계에 대해 작동하지만 OneToOne 관계에서만 작동하지만 ... 나는 당신이 옳다고 생각합니다. 이 해결책은 이번에는 작동하지 않을 것입니다 ... Grade.objects.select_related()에서 학년을 위해 그리고 나서 필터를하고 있을까요? – EroSan

+0

mysql "status;"를 살펴볼 수 있습니다. select_related는 정확히 동일한 수의 쿼리를 생성합니다. – Bufke

1

을이를 어떻게 활용할 수 있는지의 예와 " do stuff "코드를 작성하십시오. 이렇게하면 효율적으로 쿼리를 작성하는 방법을 이해할 수 있습니다.

그럼에도 불구하고, 나는 this이 도움이 될 수 있다고 생각합니다. select_related에 해당하지 않는 경우도 포함됩니다. prefetch_relatedDjango 1.4부터 사용 가능하므로이 버전으로 업그레이드해야 할 수 있습니다.

"할 일"코드를 여기에 추가하는 것이 중요합니다. 관련성이있는 경우 여기에 모델 코드를 추가하십시오 (필드 선언 만 괜찮을 것입니다) . 최적화 된 쿼리를 얻는 방법은 모델이 관련되는 방식과 쿼리 세트 결과를 사용하는 방법에 따라 다릅니다.

편집 : 마지막을 최적화 마지막 예를 들어, 당신이 할 수있는 "에 대한"하기 위해

: 당신이 grade.course 수행 select_related 부분이 예에서는

failed_grades = Grade.objects.filter(course__department=department,course__courseenrollment__user=student,grade__lte=70).select_related('course') 
for failed_grade in failed_grades: 
    print grade.course 
    print grade.grade 

을 이 쿼리는 필터링 된 성적과 관련된 모든 과정을 캐시하므로 하나의 쿼리 만 사용하면됩니다.따라서 Course 모델의 __unicode__ 메서드가 자체 필드 만 사용하면 (즉, Course의 유니 코드 메서드에서 다른 모델 데이터를 표시하지 않는 경우) 귀하의 예제에서보다 나은 성능 (쿼리 제외)을 얻게됩니다. 나는 당신이 원하는대로 문장을 위해 다른 것을 향상시키는 방법을 모르겠습니다. 하지만 이것이 당신이 원하는 것을 얻을 수 있도록 도와 줄 수 있다고 생각합니다. (어쩌면 모델을 잘 이해하지 못할 수도 있습니다.)

+0

응답 해 주셔서 감사합니다. prefetch_related가 도움이 될 명백한 방법을 보지 못했지만 더 조사해야합니다. 237 줄부터 시작하는 전체 코드 [http://code.google.com/p/student-worker-relational-database/source/browse/ecwsp/sis/report.py]를 볼 수 있습니다. 전체 소스 파일이 없어도 위 코드보다 더 완벽한 코드를 만들려고합니다. – Bufke

+0

나는 당신의 코드를 보았고 무서워졌다. 만약 200 라인이 넘는 메소드가'pod_report_grade' 라인에 있다면, 쿼리를 최적화하기 전에 더 큰 문제가있다. django 문서를 읽으십시오. [튜토리얼] (https://docs.djangoproject.com/ko/1.4/intro/tutorial01/)을 만듭니다. 그 코드가 불가능하기 때문에 다시 시작하십시오 ... – marianobianchi

+0

예, 정말, 정말 나쁩니다. 또한 수천 명의 사용자가 있으며 실제 생활은 때로는 짜증납니다. 두 번째 예제를 제공했습니다. – Bufke