2012-12-01 3 views
1

저는 장고를 처음 사용하고 있으며 데이터베이스에 ~ 60,000 개의 "프로젝트"모델이있는 응용 프로그램이 있습니다.Django Queryset을 유형별로 대체하는 방법

이 양은 항상 커질 것입니다. "프로젝트"는 우리가 만든 장고 모델입니다. 우리의 응용 프로그램은 일상적으로 이러한 프로젝트를 특정 순서로 사이트에 표시해야합니다. 우리에게는 3 가지 유형의 프로젝트가 있습니다. 유형 1, 유형 2, 유형 3이라고 부릅니다. 이 프로젝트들은 또한 특정 시간에 만료되고 그 양은 항상 커지기 때문에 우리는 정적 목록을 만들 수 없으며 동적 목록을 사용해야합니다. 우리는 (페이지 당 32)과 같은 프로젝트를 표시해야합니다 : 우리는 또한 목록에 같은 순서로 계속 필요하므로 이러한 프로젝트를 표시하는 무한 스크롤을 구현 한

type1 type2 type3 type1 
type2 type3 type1 type2 
type3 type1 type2 type3 
type1 type2 type3 type1 
type2 type3 type1 type2 
type3 type1 type2 type3 
type1 type2 type3 type1 
type2 type3 type1 type2 

. 예 : 위의 2 페이지는 type3으로 시작합니다.

  1. 지금 우리는 각 유형별로 3 가지 검색어를 만듭니다.
  2. 각각의 목록을 만듭니다.
  3. 다른 목록을 만듭니다.
  4. 그런 다음 반복되는 순서로 프로젝트를 3의 목록에 추가하십시오.
  5. Paginator를 작성하고 특정 페이지를 리턴하십시오.

나는이이 목록을 모두 작성하고 그들을 통해 반복, 매우 비싼 것을 이해하지만 난 그것을 빠르게하는 방법을 고민하고있다. 내가 시도한 한 가지 방법은 Memcached,

Memcached에 1500 개의 프로젝트를 저장하고 응답이 매우 빠릅니다. 그러나 키가 만료되면 애플리케이션은 모든 것을 다시 처리해야합니다. 내가 생각한 한 가지는 관리 명령 (https://docs.djangoproject.com/en/dev/howto/custom-management-commands/)을 작성하고 crontrab에서 실행하여이 목록이 항상 메모리에 있는지 확인하는 것입니다. 우리는 이미 crontab에서 몇 가지 명령을 실행합니다 (우리의 데이터는 가져옵니다). 그래서 이것은 끔찍하지 않을 것입니다.

필자는 필터를 사용하여 QuerySet을 생성 할 수 있다는 사실을 이용하려했지만 실제 필요가있을 때까지 데이터베이스로 이동하지 않았습니다. 그러나 페이지 당 32 개의 프로젝트가 표시되기 때문에 실제로이 문제를 구현하는 데 문제가 있습니다. 이는 한 유형의 10 개, 다른 유형의 11 개 및 다른 유형 11 개를 표시하기 때문입니다.

다른 유형의 금액이 동일하지 않습니다. 약이 :

타입 1은 : ~ 500
유형 2 : ~ 36,000
타입 3 :이 때문에 ~ 24,000

나는 또한 때 타입 1이 종료 할 때 수행하고 할 작업에 대한 문제에 달렸다 type2가 종료되었습니다. (누군가는이 사실을 알았지 만 여전히 그것을 설명 할 필요가 있습니다.)

편집 : 답변 해 주셔서 감사합니다. 이것은 내 학교 관석 프로젝트를위한 것입니다. 우리 중 누구라도 파이썬을 사용한 것은 이번이 처음입니다. 이전에 Groovy와 Grails를 인턴 과정에서 사용했기 때문에 ORM의 개념을 잘 알고 있습니다. 당신이이 쿼리를 평가하고 메모리에 목록을로드 참조 오버 헤드를 많이 가지고 수 있듯이

def index(request): 
    type1Projects = list(project.objects.filter(type=type1)) 
    type2Projects = list(project.objects.filter(type=type2)) 
    type3Projects = list(project.objects.filter(type=type3)) 

    projects = list() 

    while(len(type1Projects) > 0 or len(type2Projects) > 0 or len(type3Projects) > 0) : 
     if(len(type1Projects) > 0) : 
      projects.append(type1Projects.pop(0)) 
     if(len(type2Projects) > 0) : 
      projects.append(type2Projects.pop(0)) 
     if(len(type3Projects) > 0) : 
      projects.append(type3Projects.pop(0)) 

    paginator = Paginator(projects, 32) 

    page = request.GET.get('page', 1) 
    render_to_response('fake.html', {'projects':paginator.page(page)}, RequestContext(request)) 

: 좀 코드를 제공 할 것입니다. 그런 다음 프로젝트를 반복하고 프로젝트 목록을 만드는 데는 시간이 걸립니다.우리의 관석 클라이언트처럼 반환 된 우리를 교류 유형을 원하기 전에

:이 기능의

def index(request) : 
    projects = projects.objects.all() 

    paginator = Paginator(projects, 32) 

    page = request.GET.get('page', 1) 
    render_to_response('fake.html', {'projects':paginator.page(page)}, RequestContext(request)) 

이 단순화되는 버전의 단지 개념을 설명합니다. 두 번째 테스트는 필요한 부분 만 평가하기 때문에 빠릅니다. 모든 것이 메모리에로드 된 후 반복되므로 교대 방식은 완전히 길어집니다.

내가 장고 검색어 세트 게으른 평가의 활용하려고 노력 버전입니다 :

def index(request) : 
    type1Projects = project.objects.filter(type=type1) 
    type2Projects = project.objects.filter(type=type2) 
    type3Projects = project.objects.filter(type=type3) 

    page = request.GET.get('page', 1) 

    type1Pag = Paginator(type1Projects, 11) 
    type2Pag = Paginator(type2Projects, 11) 
    type3Pag = Paginator(type3Projects, 11) 

    type1List = list(type1Pag.page(page)) 
    type2List = list(type2Pag.page(page)) 
    type3List = list(type3Pag.page(page)) 

    projects = list() 

    while(len(type1List) > 0 or len(type2List) > 0 or len(type3List) > 0) : 
     if(len(type1List) > 0) : 
      projects.append(type1List.pop(0)) 
     if(len(type1List) > 0) : 
      projects.append(type2List.pop(0)) 
     if(len(type3List) > 0) : 
      projects.append(type3List.pop(0)) 


    render_to_response('fake.html', {'projects':projects}, RequestContext(request)) 

이 버전은 훨씬 더 빨리 작업을 수행하고이 논리가 있었기 때문에 간단한 버전은 다음 실제로 구현입니다 어느 프로젝트 유형을 시작할지 알려주고 페이지 당 32 개의 프로젝트로 제한하십시오. 그러나 한 페이지에 한 가지 유형의 프로젝트가 누락됩니다. 일단 더 먼 페이지로 가면이 유형의 목록에서 프로젝트 # 5를 시작하는 논리를 구현하는 데 어려움을 겪고 있었고 다음 페이지로 이동합니다.

나는 이것이 조금 복잡해지기를 바란다. 어제 밤에 혼란 스럽다 ... 나는 결승에 진출하려고 노력하고 있었고, 어젯밤에 똑바로 생각하지 않았을 것이다. 나는 원시 SQL과 NoSql을 살펴볼 것이다.

@ Saransh Mohapatra Redis 또는 Memcache를 정확히 사용한다는 것은 무엇을 의미합니까? Memcache를 사용하여 목록에서 처음으로 1500 개의 프로젝트를 저장합니다. 문제는 우리의 키가 5-10 분 동안 만 유효하기를 원한다는 것입니다. 따라서 키가 만료되면 누군가가 사이트로 이동하면 응답이 느려집니다. 그래서 관리 명령을 작성한 다음 4 분마다 crontab을 사용하여 키를 10 분 동안 유효하게하는 것을 말합니다. 우리가 이것을했다면 목록은 항상 거기에있을 것이지만 이것이 이것에 관해가는 가장 좋은 방법이라고 확신하지 못합니다.

+1

Welcome to Stackoverflow! 입력 내용과 문제를보다 직접적으로 말하면 질문에 대답하는 데 도움이됩니다. 명시된 바와 같이, 귀하의 문제가 정확히 무엇인지 이해하는 것은 매우 어렵습니다. – mvp

+0

원시 SQL을 사용하는 것이 좋습니다. (django queryset raw 참조). SQL이 당신의 강점이 아니라면 여기에 쿼리 작성에 대한 도움을 요청하십시오 (질문에 'SQL'과 데이터베이스 이름을 태그하십시오). 잘 작성된 SQL을 사용하면'Project.objects.raw()'가 django보다 훨씬 효율적으로이 작업을 수행 할 수 있습니다. –

답변

0

코드를 보지 않고서는 아무 것도 제안하기가 어렵습니다. 그러나 지금까지 내가 가진 모델은 관계가 없으므로 전통적인 SQL을 사용하는 대신 NoSql을 사용하면 훨씬 더 빠를 것입니다.

이렇게하면 훨씬 빨라지고 매번 캐시하지 않아도됩니다. Reddis를 보거나 캐시에만 사용하는 대신 memcache를 직접 사용할 수도 있습니다. 이들은 기본적으로 키 값 저장소의 종류입니다. 따라서 캐시 프로젝트에서 키와 세부 값이 될 수 있습니다. 둘러보기

관련 문제