Google app engine 当结果低于查询限制时,数据存储查询花费的时间太长

Google app engine 当结果低于查询限制时,数据存储查询花费的时间太长,google-app-engine,google-cloud-datastore,Google App Engine,Google Cloud Datastore,我有一个与待办应用程序相当的应用程序。在任何给定时间,都有多个挂起的任务分配给单个用户。有些用户有将近2500个待处理的任务,有些用户只有2个 当匹配查询的结果低于应用于查询的限制时,数据存储查询似乎花费的时间太长。例如: 情景1: 用户A:有2500个挂起的任务。查询限制是500,第一次请求获取的结果显然是500。所用时间:5767毫秒(5.7秒) 用户B:有2个挂起的任务。查询限制是500,第一次请求获取的结果显然是2。所用时间:7124毫秒(7.1秒) 情景2: 用户A:有2500个挂起的

我有一个与待办应用程序相当的应用程序。在任何给定时间,都有多个挂起的任务分配给单个用户。有些用户有将近2500个待处理的任务,有些用户只有2个

当匹配查询的结果低于应用于查询的限制时,数据存储查询似乎花费的时间太长。例如:

情景1:

用户A:有2500个挂起的任务。查询限制是500,第一次请求获取的结果显然是500。所用时间:5767毫秒(5.7秒)

用户B:有2个挂起的任务。查询限制是500,第一次请求获取的结果显然是2。所用时间:7124毫秒(7.1秒)

情景2:

用户A:有2500个挂起的任务。查询限制是10,第一次请求获取的结果显然是10。所用时间:~400毫秒(1/2秒)

用户B:有2个挂起的任务。查询限制是10,第一次请求获取的结果显然是2。所用时间:5-6秒

情景3:

用户A:有2500个挂起的任务。查询限制是500,第一次请求获取的结果显然是500。所用时间:6244毫秒(6秒)

用户C:有551个挂起的任务。查询限制是500,第一次请求获取的结果显然是500。所用时间:13579毫秒(13秒)

我的代码:

public static Map <String , Object> getEntitiesUsingQueryCursor( String kind , int limit , int chunkSize , String currentCursor, String account, String user, Boolean status, String dept ) throws Exception
        {

            String nextCursor = null;

            Entity entity = null;

            List <Entity> listOfEntity = new ArrayList <Entity>();

            Map <String , Object> result = new HashMap <String , Object>();


            DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
            com.google.appengine.api.datastore.Query q = new com.google.appengine.api.datastore.Query( kind );

List <Filter> listOfFilter = new ArrayList <Filter>();
Filter filter1 = new FilterPredicate( "account" , FilterOperator.EQUAL ,  account);
Filter filter2 = new FilterPredicate( "user" , FilterOperator.EQUAL ,  user);
Filter filter3 = new FilterPredicate( "dept" , FilterOperator.EQUAL ,  dept);
Filter filter4 = new FilterPredicate( "status" , FilterOperator.EQUAL ,  status); //Boolean
listOfFilter.add( filter1 );
listOfFilter.add( filter2 );
listOfFilter.add( filter3 );
listOfFilter.add( filter4 );
Filter filterParams1 = filterParams = CompositeFilterOperator.and( listOfFilter );
q.setFilter( filter );

            PreparedQuery pq = datastore.prepare( q );
            FetchOptions fetchOptions = FetchOptions.Builder.withLimit(limit).prefetchSize( chunkSize ).chunkSize( chunkSize );

            if ( !StringUtil.isBlank( currentCursor ) )
                fetchOptions.startCursor( Cursor.fromWebSafeString( currentCursor ) );

            QueryResultIterable <Entity> results = pq.asQueryResultIterable( fetchOptions );
            QueryResultIterator <Entity> iterator = results.iterator();

            while ( iterator.hasNext() )
                {
                    entity = iterator.next();
                    listOfEntity.add( entity );
                }

            if(listOfEntity.size() == limit)
                nextCursor = iterator.getCursor().toWebSafeString();

            result.put( "cursor" , nextCursor );
            result.put( "entity" , listOfEntity );

            return result;
        }
public static Map getEntitiesUsingQueryCursor(字符串种类、int限制、int chunkSize、字符串currentCursor、字符串帐户、字符串用户、布尔状态、字符串部门)引发异常
{
字符串nextCursor=null;
实体=空;
List-listOfEntity=new-ArrayList();
Map result=newhashmap();
DatastoreService datastore=DatastoreServiceFactory.getDatastoreService();
com.google.appengine.api.datastore.Query q=new com.google.appengine.api.datastore.Query(种类);
List-listofilter=newarraylist();
Filter filter1=新的FilterPredicate(“帐户”,FilterOperator.EQUAL,account);
Filter filter2=新的FilterPredicate(“用户”,FilterOperator.EQUAL,用户);
Filter filter3=新的FilterPredicate(“部门”,FilterOperator.EQUAL,dept);
Filter filter4=新的FilterPredicate(“状态”,FilterOperator.EQUAL,status);//布尔值
添加过滤器列表(过滤器1);
添加过滤器列表(过滤器2);
添加过滤器列表(过滤器3);
添加过滤器列表(过滤器4);
Filter filterParams1=filterParams=CompositeFilterOperator.and(listOfFilter);
q、 设置过滤器(过滤器);
PreparedQuery pq=数据存储。prepare(q);
FetchOptions FetchOptions=FetchOptions.Builder.withLimit(limit).prefetchSize(chunkSize).chunkSize(chunkSize);
如果(!StringUtil.isBlank(currentCursor))
fetchOptions.startCursor(Cursor.fromWebSafeString(currentCursor));
QueryResulterable结果=pq.asQueryResulterable(获取选项);
QueryResulterator迭代器=results.iterator();
while(iterator.hasNext())
{
entity=iterator.next();
实体列表。添加(实体);
}
if(listOfEntity.size()=限制)
nextCursor=iterator.getCursor().TowersFestring();
结果。放置(“光标”,下一个光标);
结果。put(“实体”,实体清单);
返回结果;
}
数据存储查询就是这样工作的吗?有人能提出更好的查询实体的方法吗?如果我将查询的平均限制设置为50,则拥有少于50个挂起任务的用户必须等待至少7秒才能在页面上获取任务。即使我将限制设置为10,并且用户只有2个挂起的任务,7秒的时间也适用。

如果您定义一个on
帐户、用户、部门、状态
回答上述查询只需要对单个索引进行线性扫描,这将大大提高查询速度(无论限制如何)

举例来说,假设你有

[行][账户、用户、部门、状态][实体]
1] A、B、C、D、e1
2] A B E F e2
3] A B E F e3
4] A、F、A、e4
5] B A Z E e5

'A B E F'
的查询将找到行
[2]
,然后线性扫描到
[3]
返回
[e1,e2]
。它将停止在做了很少工作的
[4]
(不匹配的第一行)

猜测一下,您的查询必须为每个筛选器扫描一个索引。查看索引如何影响查询性能。@snakecharmerb当查询限制为10且匹配筛选器的结果超过2500时,延迟为400毫秒。如果我应用相同的查询,并且匹配筛选器的结果为2(小于限制10),则所用时间为5-6秒。这真的是关于索引吗?可能是。考虑:数据存储中的匹配限制为10和2500+个,查询引擎可以在找到10个匹配后停止查询。对于数据存储中的限制10和2个匹配项,查询引擎将在返回之前读取可能是匹配项的所有记录。因此,限制大于匹配数的查询保证具有最坏的性能。然后问题就变成了,如何缓解这种情况?一个可能的答案是制定索引,以便在最坏的情况下最大限度地提高性能。另一个答案是取消限制,但我认为这不是一个选项。@snakecharmerb谢谢,让我看一下文档,然后回到you@snakecharmerb如果这听起来很愚蠢,请原谅,但我的查询没有排序顺序。我只有4个“equals”过滤器,这根本不需要任何索引,为其他查询添加的现有索引会影响我的结果吗?