2017-10-21 3 views
1

날짜가있는 고유 레코드가 포함 된 장고 모델이 있습니다. 현재 기록을 일 단위로 계산하고 있습니다 (예 : X 번호가 이미 오늘 날짜로 전달되고, X가 다음 10 일 이내에 발생하고, X가 다음 30 일 이내에 발생합니다. 아래 코드는 현재 사용하고있는 것으로, 모델에 대한 records.objects.all() 쿼리에서 모든 값을 다시 가져온 다음 각 개체를 반복하여 datetime 델타를 계산하고 관련 카운터를 증가시킵니다.일짜의 날짜/시간 diff의 실행자 계산

이 내가 좋아하는 것보다 더 이상 5-6 초 정도 걸립니다 약 50,000 레코드
for x in records: 
    if x.date is None: 
     missingValue += 1 
    else: 
     delta = x.date - date.today() 
     if delta.days < 0: 
      passed += 1 
     if delta.days < 10: 
      tenDays += 1 
     if delta.days < 30: 
      thirtyDays += 1 

, 내가 기록의 수가이 감소 노력하고있어 증가 할 가능성이있다. 질문은 실제로 datetime diffs의 성능 계산과 Django Query 또는 다른 방법을 통해 더 나은 방법이있는 것처럼 결과 일 수를 그룹화하는 것입니다. 시도하지 못했던 다른 방법을 찾았습니다.

원시 SQL에서 DateAdd를 사용하는 방법을 살펴 보았지만 각 날짜 범위에 대해 데이터베이스를 쿼리해야 할 필요가있는 것처럼 보였으 나 결과를 반복해야했습니다.

+0

데모 샘플 데이터를 원하는 출력 http://www.rextester.com을 준비하시기 바랍니다. 순수한 SQL에서는 1 초 미만의 시간을 얻을 수 있다고 확신합니다. – lad2025

+1

http://rextester.com/AWPX46055 - 그럴 권리가 있다고 생각하십시오. 원하는 결과물은 위의 그룹에 의한 숫자의 반환 일 뿐이며 30 일 이내에 10 일 이내에 전달됩니다. 나는 또한 30 일이 넘는 것에 대한 미래의 필요성을 안다. 내부 날짜는 누적됩니다. – Draineh

+1

샘플 데이터를 보내 주셔서 감사합니다 – lad2025

답변

1

사용하여 SQL은 COUNT 윈도우 모드 :

WITH cte AS (
    SELECT *,CASE WHEN DATEDIFF(DAY,GETDATE(),targetdate) <=0 THEN 0 
        WHEN DATEDIFF(DAY,GETDATE(),targetdate) <=10 THEN 10 
        WHEN DATEDIFF(DAY,GETDATE(),targetdate) <=30 THEN 30 
        ELSE 31 END AS grp 
    FROM [record] 
    --WHERE targetdate > GETDATE() - 60 -- last 60 days 
) 
SELECT DISTINCT grp, COUNT(*) OVER(ORDER BY grp) AS running_count 
FROM cte; 

Rextester Demo

+1

감사합니다. 지금은 두 번째 응답 시간입니다. – Draineh

1

성능을 최적화하기 전에 일괄 적으로 실행하는 것이 좋습니다. 가장 작은 창은 1 일로 보입니다.

from datetime import datetime, timedelta 
records.objects.filter(updated__lt = datetime.now()-timedelta(days=1))[:2083] 

하고 작업을 수행 그래서 레코드 모델의 '업데이트'필드를 필터링하여, 당신은을 (크론 당) 매 시간마다 호출 할 수 있습니다. 검색된 레코드 수를 제한 할 수 있습니다. 따라서 매 시간마다 2083 개 (또는 5000 개)의 레코드가 처리됩니다. 이 숫자는 데이터베이스의 레코드 수 (예 : 50000/24 ​​= 2083)를 기준으로 확장 할 수 있습니다.

또한 이전 라이브 레코드를 한 번 처리하도록 이전 설정을 반영하고 싶을 수도 있습니다 처음에는

+0

가장 작은 창은 1 일입니다. 지금은 결과를 가져 와서 사용자에게 직접 제시합니다 (문제의 일부). 이 접근 방식을 사용하면 결과를 캐싱하고 사용자가 수치를보고 계산할 때마다 호출하도록 할 수 있습니다. – Draineh

+1

예, 여기서 중요한 것은'Model.objects.all() 데이터베이스에 대한 스트레스를 줄이기 위해 필터링에 대해 고려해야합니다. 다른 필터링 방법을 찾을 수 있다면 좋습니다. E.G. 사용자가 작업을 수행 할 때 해당 사용자와 관련된 모든 레코드를 업데이트하십시오. 일괄 처리는 철저한 해결책이며 잊어 버린 기록을 피할 수 있습니다. – rollinger