如何扫描数据存储区中的大表

时间:2014-03-07 12:37:37

标签: google-cloud-datastore

这是我的问题..

我们有一个拥有超过5000万用户的用户表。现在我想检索一些测试方法所需的fbId(即readUsersByFacebookIds())

我天真的第一次尝试是扫描一些非空的facebookId然后使用那些fbIds的记录。这个问题超时了,我的同事提到DataStore可能很难用NOT_EQUAL。即不能使用索引。 (听起来很合理......)

尝试#1超时,即> 60秒

public String testFbFriends(int count) {
    try {
        DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
        Query q = new Query("User");
        q.setFilter(new FilterPredicate("facebookId", Query.FilterOperator.NOT_EQUAL, null));
        PreparedQuery pq = ds.prepare(q);
        List<String> fbIds = new ArrayList<String>();
        for (Entity userE : pq.asIterable(FetchOptions.Builder.withLimit(count).chunkSize(100))) {
            User u = new User(1, userE, false);
            fbIds.add(u.getFacebookId());
            if (fbIds.size() >= count)
                break;
    }           

        List<User> users = UserModule.getInstance().readUsersByFacebookIds(1, fbIds, 0, 0);

        return jsn.toJson(users);
    } catch (Exception e) {
        return STR.getStackTrace(e);
    }
}

我的第二次尝试是扫描一些用户并跳过那些facebookId为空的用户。

尝试#2 - 也超时......

public String testFbFriends(int count) {
    try {
        DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
        Query q = new Query("User");
        // q.setFilter(new FilterPredicate("facebookId", Query.FilterOperator.NOT_EQUAL, null));
        PreparedQuery pq = ds.prepare(q);
        List<String> fbIds = new ArrayList<String>();
        for (Entity userE : pq.asIterable(FetchOptions.Builder.withLimit(count * 4).chunkSize(100))) {
            User u = new User(1, userE, false);
            if (u.getFacebookId() != null) {
                fbIds.add(u.getFacebookId());
                if (fbIds.size() >= count)
                    break;
            }
    }           

        List<User> users = UserModule.getInstance().readUsersByFacebookIds(1, fbIds, 0, 0);

        return jsn.toJson(users);
    } catch (Exception e) {
        return STR.getStackTrace(e);
    }
}

所有人都知道如何从巨大的桌面扫描一些记录吗?

提前非常感谢!

1 个答案:

答案 0 :(得分:0)

您是否尝试过使用游标?

 ...
Query q = new Query("User");

if (cursorString != null) {
    Cursor cursor = Cursor.fromWebSafeString(cursorString);
        Map<String, Object> extensionMap = new HashMap<String, Object>();
        extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
        q.setExtensions(extensionMap);
}
q.setRange(0, range);
...retrieve entities...
Cursor cursor = JDOCursorHelper.getCursor(results);
cursorString = cursor.toWebSafeString();
...  

使用游标,您可以设置每次调用中检索到的实体数量,并避免超时。