Skip to main content
 首页 » 编程设计

python之获取并迭代大型数据集,可以吗为什么管理日志/appstas 不同

2025年05月04日23hnrainll

当尝试优化查询以根据位置获取商店记录时,我陷入了一些奇怪的事情(我认为),获取大型数据集需要大量的 CPU 时间。

基本上我有 > 1000 条记录需要迭代以找到用户位置 3000 米范围内的商店,我在管理控制台中得到了相当多的数字。

这导致了一些数据存储测试,这些测试产生了一些有趣的数字以获取 1000 条记录。

我有 6 种测试方法要单独运行,并从管理控制台和应用程序统计中占用 CPU 时间,结果是这样的(在生产中):

    r = db.GqlQuery("SELECT __key__ FROM StoreRecords").fetch(1000) 
    # appstats: real=120ms cpu=182ms api=845ms 
    # admin console: 459ms 1040cpu_ms 845api_cpu_ms 
 
    r = db.GqlQuery("SELECT __key__ FROM StoreRecords").fetch(100) 
    # appstats: real=21ms cpu=45ms api=95ms 
    # admin console: 322ms 134cpu_ms 95api_cpu_ms 
 
    r = db.GqlQuery("SELECT * FROM StoreRecords").fetch(1000) 
    # appstats: real=1208ms cpu=1979ms api=9179ms 
    # admin console: 1233ms 10054cpu_ms 9179api_cpu_ms 
 
    r = db.GqlQuery("SELECT * FROM StoreRecords").fetch(100) 
    # appstats: real=57ms cpu=82ms api=929ms 
    # admin console: 81ms 1006cpu_ms 929api_cpu_ms 
 
    r = model.StoreRecords.all().fetch(1000) 
    # appstats: real=869ms cpu=1526ms api=9179ms 
    # admin console: 1061ms 9956cpu_ms 9179api_cpu_ms 
 
    r = model.StoreRecords.all().fetch(100) 
    # appstats: real=74ms cpu=86ms api=929ms 
    # admin console: 97ms 1025cpu_ms 929api_cpu_ms 

这里我最多只取 1000 条记录,但需要全部取回(大约 4-5000 条)。

我的问题是:

  1. 获取 1000 条记录真的需要将近 20 (10054cpu_ms + 9179api_cpu_ms) 秒吗?
  2. 为什么应用程序时间和管理控制台时间不同?根据我的配额计算什么?

通过将获取的记录作为 protobuf 推送到内存缓存,可以轻松解决这个问题。但我很好奇应用程序和管理控制台之间的高使用率和时间差异。

奖励问题: 为什么提取 1000 条记录总是导致 9179api_cpu_ms?

请您参考如下方法:

为什么检索大量记录需要大量资源令人惊讶?这是一个 O(n) 过程,您真的不应该在每个请求的基础上执行此操作。按顺序回答您的问题:

  1. 它使用多少 CPU 时间取决于记录的性质,但这个结果并不奇怪。请注意,它接近 20 CPU 秒,而不是挂钟秒。另请注意,当新的计费模型推出时,您需要为数据存储操作和实例小时数付费,这是您应该优化的内容。
  2. 管理控制台会显示您计费所依据的权威数字。 appstats 数字较低,因为它们只计算 API 调用期间花费的时间,而不计算执行您自己的代码所花费的时间。

如果您的记录集很小并且相当静态,您应该将它们缓存在实例内存中,而不是每次都获取它们或将它们存储在内存缓存中。如果它们更大且动态,您应该使用 GeoModel 之类的东西,这样您就可以进行地理查询并仅获取相关记录。

获取 1000 条记录始终需要相同数量的 API CPU 时间,因为它是数据存储访问成本的表示方式 - 这不是实际花费的时间。新模型通过将其分解为单独的计费操作来解决此问题。