문제

나는 Valor라는 모델입니다. 용기에는 로봇이 있습니다. 나는 다음과 같이 쿼리하고있다 :

Valor.objects.filter(robot=r).reverse()[0]

마지막 용기를 얻으려면 R 로봇. Valor.objects.filter (robot = r) .count ()는 약 200000이고 마지막 항목을 얻는 데는 약 4 초가 걸립니다.

속도를 어떻게 올릴 수 있습니까? 잘못된 길을 쿼리하고 있습니까?

도움이 되었습니까?

해결책

데이터 세트가 사물을 조금씩 제거하고 싶을 정도로 커질 것 같습니다. 로봇 개체에서 마지막 용기 개체를 추적해 보셨습니까?

class Robot(models.Model):
    # ...
    last_valor = models.ForeignKey('Valor', null=True, blank=True)

그런 다음 a post_save 신호 업데이트를 위해.

from django.db.models.signals import post_save

def record_last_valor(sender, **kwargs):
    if kwargs.get('created', False):
        instance = kwargs.get('instance')
        instance.robot.last_valor = instance

post_save.connect(record_last_valor, sender=Valor)

Valor Objects를 만들 때 추가 DB 트랜잭션 비용을 지불하지만 Last_valor 조회는 빠르게 타격을 줄 것입니다. 그것과 함께 플레이하고 트레이드 오프가 앱에 가치가 있는지 확인하십시오.

다른 팁

이 문제에 대한 최적의 MySQL 구문은 다음의 선을 따라 무언가가 될 것입니다.

SELECT * FROM table WHERE x=y ORDER BY z DESC LIMIT 1

이에 동등한 Django는 다음과 같습니다.

Valor.objects.filter(robot=r).order_by('-id')[:1][0]

이 솔루션이 Django의 사용 방법에 주목하십시오 슬라이스 쿼리 세트를 제한하는 메소드 ~ 전에 객체 목록을 컴파일합니다.

이전 제안 중 어느 것도 작동하지 않으면 Django를 방정식에서 꺼내고 데이터베이스에 대해이 원시 SQL을 실행하는 것이 좋습니다. 테이블 이름을 추측하고 있으므로 그에 따라 조정해야 할 수도 있습니다.

SELECT * FROM valor v WHERE v.robot_id = [robot_id] ORDER BY id DESC LIMIT 1;

느린가요? 그렇다면 RDBMS (MySQL?)가 귀하에게 쿼리 계획을 설명하십시오. 이것은 전체 테이블 스캔을하고 있는지 알려줄 것입니다. 질문을 편집하고 스키마를 포함시킬 수도 있습니다. valor 우리가 볼 수있는 테이블.

또한 Django 가이 작업을 수행하여 생성하는 SQL을 볼 수 있습니다 (Peter Rowell이 제공 한 쿼리 세트).

qs = Valor.objects.filter(robot=r).order_by('-id')[0]
print qs.query

SQL이 위에 게시 한 '원시'쿼리와 유사한 지 확인하십시오. RDBMS에서 쿼리 계획을 설명 할 수도 있습니다.

글쎄, order_by 절은 없으므로 '마지막'이 무슨 뜻인지 궁금합니다. 당신이 '마지막 추가'를 의미한다고 가정하면

Valor.objects.filter(robot=r).order_by('-id')[0]

당신을 위해 일을 할 수 있습니다.

django 1.6은 .first () 및 .last ()를 소개합니다.

https://docs.djangoproject.com/en/1.6/ref/models/querysets/#last

그래서 당신은 단순히 할 수 있습니다 :

Valor.objects.filter(robot=r).last()

상당히 빠른 것도 다음과 같아야합니다.

qs = Valor.objects.filter(robot=r) # <-- it doesn't hit the database
count = qs.count()                 # <-- first hit the database, compute a count
last_item = qs[ count-1 ]          # <-- second hit the database, get specified rownum

따라서 실제로는 2 개의 SQL 쿼리 만 실행합니다.)

Django에 한계 조항이 있습니까? 이렇게하면 DB를 가질 수 있습니다. 단일 레코드를 반환하십시오.

MySQL

 select * from table where x = y limit 1

SQL 서버

 select top 1 * from table where x = y

신탁

 select * from table where x = y and rownum = 1

나는 이것이 Django로 번역되지 않았다는 것을 알고 있지만 누군가가 돌아와서 이것을 청소할 수 있습니다.

이 작업을 수행하는 올바른 방법은 내장 쿼리 세트 메소드를 사용하여 최신 ()을 사용하여 정렬 해야하는 열 (필드 이름)을 공급하는 것입니다. 단점은 단일 DB 열로 만 정렬 할 수 있다는 것입니다.

현재 구현은 이와 같이 보이며 @aaron의 제안과 같은 의미로 최적화되어 있습니다.

def latest(self, field_name=None):
    """
    Returns the latest object, according to the model's 'get_latest_by'
    option or optional given field_name.
    """
    latest_by = field_name or self.model._meta.get_latest_by
    assert bool(latest_by), "latest() requires either a field_name parameter or 'get_latest_by' in the model"
    assert self.query.can_filter(), \
            "Cannot change a query once a slice has been taken."
    obj = self._clone()
    obj.query.set_limits(high=1)
    obj.query.clear_ordering()
    obj.query.add_ordering('-%s' % latest_by)
    return obj.get()
Model_Name.objects.first()

// 첫 번째 요소를 얻으려면

Model_name.objects.last()

// get last ()

내 경우에는 마지막으로 데이터베이스에 행이 하나만 있으면 작동하지 않습니다. :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top