【问题标题】:Google App Engine - Too many Datastore Read OperationsGoogle App Engine - 数据存储区读取操作过多
【发布时间】:2012-10-08 00:13:45
【问题描述】:

我已经通过 Google App Engine 为我的 Android 应用实施了在线排行榜。但 2 小时后,我在“数据存储读取操作”中达到了 100% 的配额。谁能帮我修改我的代码以减少读取操作?
这是我的代码:

public class The_Big_Bang_Theory_Quiz_HighscoreserverServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String game = req.getParameter("game");
    String name = req.getParameter("name");
    String pointsStr = req.getParameter("points");
    String behaviorStr = req.getParameter("behavior");
    int behavior = 0; // 0 = upload, 1 = download
    if (behaviorStr != null) {
        try {
            behavior = Integer.parseInt(behaviorStr);
        } catch (NumberFormatException e) {
            behavior = 0;
        }
    }
    if (behavior == 0) {
        int points = 0;
        if (pointsStr != null) {
            try {
                points = Integer.parseInt(pointsStr);
            } catch (NumberFormatException e) {
                points = 0;
            }
        }
        if (points > 0 && name != null) {
            addHighscore(game, name, points);
        }
    } else {
        String maxStr = req.getParameter("max");
        int max = 1000;
        if (maxStr != null) {
            try {
                max = Integer.parseInt(maxStr);
            } catch (NumberFormatException e) {
                max = 1000;
            }
        }
        returnHighscores(resp, game, max);
    }
}

private void returnHighscores(HttpServletResponse resp, String game, int max) {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Key gameKey = KeyFactory.createKey("game", game);
    Query query = new Query("highscore", gameKey);
    query.addSort("points", Query.SortDirection.DESCENDING);
    List<Entity> highscores = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(max));
    for(Entity e : highscores) {
        try {
            resp.getWriter().println(e.getProperty("name") + ";" +e.getProperty("points"));
        } catch (IOException exc) {
            exc.printStackTrace();
        }
    }
}

private void addHighscore(String game, String name, int points) {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Key gameKey = KeyFactory.createKey("game", game);
    Entity highscore = new Entity("highscore", gameKey);
    highscore.setProperty("name", name);
    highscore.setProperty("points", points);
    datastore.put(highscore);
}
}

我读到了一些关于BlobStore 的信息。这是更好的方法吗?

【问题讨论】:

  • 缓存!如果这还不够,请缓存更多!

标签: android google-app-engine google-cloud-datastore quota


【解决方案1】:

仅供参考,如果您是 GAE 的enable the AppStats option,您可以获得一份很酷的报告,该报告准确地告诉您每个数据库事务的时间和成本。

这在尝试调试资源使用情况时非常有用。

【讨论】:

【解决方案2】:

我遇到了同样的问题,我使用 GEA 的缓存机制来解决问题。 基本上 Cache 是一个分布式 HasMap

一些代码: 创建地图:

try {
            cache = CacheManager.getInstance().getCacheFactory().createCache(
                    new ConcurrentHashMap<String, Category>());
        } catch (CacheException e) {
            Logger
                    .getLogger(TipsDAO.class.getName())
                    .severe(
                            "unable to cretate cache using an internal ConcurrentHashMap");
            cache = new ConcurrentHashMap<String, Category>();
        }

对于每次读取的弹出窗口,您首先检查 Map,如果找到 i 则返回,如果未找到,则从 DB 中读取并将其放入 Map 中,然后再返回。

if (cache.containsKey(cat)) {
            return (Category) cache.get(cat);
        }
        try {
            Query query = entityManager
                    .createQuery("SELECT FROM Category WHERE name = ?1");
            query.setParameter(1, cat);
            Category temp = (Category) query.getSingleResult();
            cache.put(cat, temp);
            return temp;
        } catch (Exception e) {
            LOG.severe(e.getMessage());
            return null;
        }

对于数据库的每个写入操作,您还写入地图

cache.put(cat.getName(), cat);

【讨论】:

  • 感谢您的帖子!你能告诉我什么是“猫”吗?其次,这一行:“cache = new ConcurrentHashMap();”为什么没有类型不匹配?缓存和地图?最好的问候!
  • cat 是我的一个域类,都是真实代码的复制粘贴...缓存是 MAP 类型,但它是 google 实现的。
  • 您是否可以将代码发送给我(例如通过邮件),以便我更好地理解它?问候。
  • 完整代码我无法发送给您,但请随时询问更多信息,我很乐意为您提供帮助。明天我将尝试使我的代码示例更通用,也许这也会有所帮助。这个想法很简单,您可以使用 Map 来减少 DB 调用。
  • 明天我会尽量让我的代码示例更通用,这将非常有帮助!我不知道我是否正确理解了整体。如果我将某些内容放入缓存中,那么它也会存储在数据存储中吗?因为你写了如果你没有找到它,你就从数据库中读取
【解决方案3】:

读取操作返回的每个实体都需要读取操作。您在免费配额下有 50k 读取操作。

每当您获得高分时,您似乎都会获得 1000 个高分。如果你的分数 > 1000,那么拉分数 50 次就会达到你的极限。

您的用户真的关心前 1000 名的分数吗?这是你的决定,但我非常怀疑。如果您获得了前 10 名的高分,那么在您用完配额之前,您的查询次数可能会增加 100 倍。

下一步省钱是使用投影查询,这样您的读取就使用小型操作而不是读取操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    相关资源
    最近更新 更多