2013-02-03 7 views
4

Google 데이터 스토어에서 100k + 엔티티의 경우 ndb.query(). count()는 색인을 포함하여 마감일까지 취소됩니다. 나는 produce_cursors 옵션으로 시도했지만 iter() 또는 fetch_page() 만 커서를 반환하지만 count()는 반환하지 않습니다.큰 엔티티에서 ns.query.count()가 60s 쿼리 마감일에 실패했습니다

큰 개체는 어떻게 계산합니까?

+0

동일한 문제가 작업 대기열에 있습니다. 문제는 프론트 엔드 요청에 대한 60 초짜리'DeadlineExceededError'가 아니고, 쿼리 자체에 대한 60 초 (ish?) 기한입니다. _ToDatastoreError (err) ... 시간 초과 : 데이터 저장소 작업 시간이 초과되었습니다. 또는 데이터를 일시적으로 사용할 수 없었습니다. "글쎄, 그건 OP의 문제라고 생각해. –

답변

2

Task Queue Python API을 살펴보세요. Google App Engine은 Task Queue API를 기반으로 deferred library을 제공하며 백그라운드 작업을 실행하는 전체 프로세스를 단순화하는 데 사용할 수 있습니다.

import logging 

def count_large_query(query): 
    total = query.count() 
    logging.info('Total entities: %d' % total) 

는 그런 다음처럼 응용 프로그램 내에서 위의 함수를에서 호출 할 수 있습니다 : 여기

은 앱에서 연기 라이브러리를 사용할 수있는 방법의 예입니다

from google.appengine.ext import deferred 

# Somewhere in your request: 
deferred.defer(count_large_query, ndb.query()) 

count()이 큰 데이터 저장소로 결과를 반환하는지 확실하지는 않지만 커서를 사용하는이 count_large_query() 함수를 대신 사용할 수 있습니다 (untes 테드) :

LIMIT = 1024 
def count_large_query(query): 
    cursor = None 
    more = True 
    total = 0 
    while more: 
    ndbs, cursor, more = query.fetch_page(LIMIT, start_cursor=cursor, keys_only=True) 
    total += len(ndbs) 

    logging.info('Total entitites: %d' % total) 

위 세트 4에 LIMIT 로컬 시도하고 콘솔에서 당신이 Total entitites: ## 라인을 볼 수 있는지 확인합니다.

(이 문제를 연기 할 수 있지만)이 여전히 확장되지 않습니다 귀도는이 중 하나를 확장하지 않을 것이다 주석에서 언급 한 바와 같이


. 작업에는 1 분이 아닌 10 분이 있으므로 많은 항목으로 10 배로 계산할 수 있습니다. 그러나 그것은 꽤 비싸다! 이 문제를 올바르게 해결하려면 샤드 화 된 카운터를 검색하십시오 (불행히도 많은 작업이 입니다).

따라서 best practices for writing scalable applications과 특히 sharding counters을 살펴볼 수 있습니다.

+1

흠. 이것은 여전히 ​​확장되지 않습니다 (문제가 연기 될 수 있음). 작업에는 1 분이 아닌 10 분이 있으므로 어쩌면 많은 항목을 10 배로 계산할 수 있습니다. 그러나 그것은 꽤 비싸다! 이 문제를 적절하게 해결하려면 샤드 카운터를 검색하십시오 (불행히도 많은 작업). –

+0

@RayYan Guido의 의견을 듣고 답을 업데이트했습니다. 고려해보십시오. – Lipis

1

Google 앱 엔진 백엔드를 사용하는 것이 좋습니다. 백엔드는 사용자 요청의 60 초 기한 및 작업 마감일 10 분을 면제하고 무기한 실행됩니다. 여기에서 문서를 보시기 바랍니다 : https://developers.google.com/appengine/docs/java/backends/overview

+0

감사하지만 백엔드까지도 쿼리 마감 기한은 피할 수 없습니다. –

+1

이것은 사실입니다. 데이터베이스 API는 호출하는 플랫폼이 아니라 시간 초과됩니다. 비슷한 질문이나 답을 찾았을 때 피할 수없는 것입니다. –

2

이것은 실제로 실망스런 문제입니다. 나는 최근 몇 가지 일반적인 통계 (기본적으로 쿼리를 만족시키는 엔티티의 수)를 얻기 위해이 영역에서 몇 가지 작업을 수행해 왔습니다. count()은 좋은 생각이지만 데이터 저장소 RPC 시간 초과로 인해 혼란 스럽습니다.

count() 커서가 어떤 식 으로든 지원되는 경우, 결과 집합 전체에 커서를 놓고 큰 숫자의 키 목록 만 반환하면 결과 집합 전체에 커서를 놓을 수있어 좋을 것입니다. 커서를 사용하면 "배턴 패스"지연 접근 방식을 사용하여 1 분/10 분 경계 전체에서 계속 진행할 수 있습니다. count()을 사용하면 (예 : fetch(keys_only=True)) 낭비를 크게 줄이고 RPC 호출 속도를 높일 수 있습니다.백도어에 대한 비싼 제안 인 fetch(keys_only=True) 접근 방식을 사용하면 1,000,000까지 셀 수있는 놀라운 시간이 필요합니다.

주기적 통계 통계 (예 : 국가의 시스템에있는 모든 계정의 일일 통계) 만 필요하거나 필요로하는 경우에는 통계 카운터에 많은 비용이 듭니다.

+0

여기의 해결책은 대신 커서를 지원하는'db.Query.count'를 사용하는 것입니다. 카운트가 수백만에 달하면 몇 분에서 몇 초 사이의 차이입니다. 'deferred.defer'를 사용하여 결과를 저장하고 전달하면 두 번의 60 초 요청에서 최대 2 백만을 셀 수 있습니다. 'db.Query.count'는'ndb' 매핑을 사용하는 경우에도 사용할 수 있습니다. – technomage