2011-06-14 2 views
1

외부 데이터 소스에서 가져온 데이터 저장소에 많은 양의 항목 (제품)이 있습니다. 매일 업데이트를 확인하고 싶습니다.App Engine : 데이터 저장소에서 데이터를 업데이트하지 않는 동안 데이터 저장소에서 데이터를 확인하는 가장 좋은 방법

일부 항목은 응용 프로그램에서 직접 가져온 항목이므로 이미 업데이트되었습니다. 일부는 새로 삽입되며 업데이트가 필요하지 않습니다.

가져온 것이 아닌 경우 나는 cron 작업을 실행 중입니다. 파이썬 API를 사용합니다.

현재 다음을 수행합니다.

는 내가 가장 오래된 항목을 선택하고 업데이트를 예약 할 수

query = dbmodel.product.all() 
query.filter('dateupdated <', newdate) 
query.order('dateupdated')   
results = query.fetch(limit=mylimit, offset=myoffset) 

을 사용할 수 있습니다

dateupdated = db.DateTimeProperty(auto_now_add=True) 

필드를 가지고있다. 작업 대기열을 사용자 정의 작업 이름과 함께 사용하여 각 제품 업데이트가 하루에 한 번만 실행되도록했습니다.

문제는 제품의 데이터가 변경되지 않았더라도 데이터 업데이트 기록을 의미하는 필드 dateupdated를 업데이트해야한다는 것입니다. 업데이트 프로세스를 추적하기 위해서입니다.

이렇게하면 많은 리소스 (CPU 시간, Datastore API 호출 등)가 소모됩니다.

이러한 작업을 수행하고 불필요한 데이터 저장소 쓰기를 방지하는 더 좋은 방법이 있습니까?

+0

왜 내가 dateupdated 필드를 업데이트했는지 확신 할 수 없었습니다. 왜 우리가 수표를 발행 한 마지막 날짜를 저장하지 않고 오프셋을 사용하지 않고 그것을 사용했는지는 알 수 있습니다. 그러나 어느 쪽이든, 나는 커서가 당신이 찾고있는 것이라고 생각합니다. –

+0

하루에 한 번 쿼리를 실행하면 마지막으로 확인했을 때 필터링 할 필요가 없습니다. 모든 제품은 적어도 하루 전, 귀하가 마지막으로 프로세스를 실행했을 때 검사되었을 것입니다. 어떤 경우 든, 수백만 개의 제품을 다루지 않는 한, 레코드에 타임 스탬프를 몇 개 작성하는 것은 CPU 시간을 크게 부과하지 않습니다. –

+0

@Nick Johnson I 이미 다른 프로세스에서 업데이트했거나 새로운 항목을 제외하기 위해 필터링합니다. 작업 대기열에서 사용자 지정 이름을 사용하여 하루에 두 개 이상의 제품 업데이트를 예약 할 수 없으므로이 작업을 건너 뛸 수도 있습니다. 문제는 무엇이 더 효율적인가? 어쨌든, 제 이해는'myproduct = product.get_by_key_name (productkey) myproduct.dateupdated = datetime.datetime.now() product.put (myproduct)'과 같은 것을 사용하는 것이 전체 entitiy를 다시 저장하는 것과 같습니다.또는 변경된 필드를 업데이트하고 CPU 사용량을 줄이는 것이 좋습니다. –

답변

1

예, 당신은 당신의 실체를 처리 한 후 커서를 저장 한 후 dateupdated하여 쿼리를 주문에 의해

cursors를 사용하여, 당신은 단지 마지막 쿼리 이후에 업데이트 항목을 얻기 위해 나중에 동일한 쿼리를 다시 실행할 수 있습니다.

그래서, 당신은 할 수

class MyEntity(db.model): 
    dateupdated = db.DateTimeProperty(auto_now_add=True) 

설치 핸들러와 같은 클래스 주어진이 같은 작업으로 실행되도록 :

class ProcessNewEntities(webapp.RequestHandler): 
    def get(self): 
     """Run via a task to process batches of 'batch_size' 
     recently updated entities""" 
     # number of eneities to process per task execution 
     batch_size = 100 
     # build the basic query 
     q = MyEntity.all().order("dateupdated") 
     # use a cursor? 
     cursor = self.request.get("cursor") 
     if cursor: 
      q.with_cursor(cursor) 
     # fetch the batch 
     entities = q.fetch(batch_size) 
     for entity in entities: 
      # process the entity 
      do_your_processing(entity) 
     # queue up the next task to process the next 100 
     # if we have no more to process then delay this task 
     # for a while so that it doesn't hog the application 
     delay = 600 if len(entities)<batch_size else 0 
     taskqueue.add(
      url='/tasks/process_new_entities', 
      params={'cursor': q.cursor()}, 
      countdown=delay) 

다음은 작업 실행의 시작을 트리거 할 필요가 like :

def start_processing_entities(): 
    taskqueue.add(url='/tasks/process_new_entities') 
+0

유망한 설명을 해주셔서 감사합니다. 내가 보는 유일한 문제는'query.filter ('dateupdated <', newdate)'와 같은 필터를 사용할 수 없다는 것입니다. 그러나 나는 그것을 해결할 방법이 있다고 확신한다. –

관련 문제