删除所有Blobstore数据的最简单方法是什么?

4 投票
2 回答
2273 浏览
提问于 2025-04-17 01:46

你有什么好的方法可以从blobstore中删除所有的blob吗?我在用Python。

我有很多blob,想把它们全部删除。现在我正在做以下操作:

class deleteBlobs(webapp.RequestHandler): 
    def get(self): 
        all = blobstore.BlobInfo.all(); 
        more = (all.count()>0) 
        blobstore.delete(all); 
        if more: 
            taskqueue.add(url='/deleteBlobs',method='GET'); 

但看起来这占用了很多CPU资源,而且(就我所知)似乎没有做什么有用的事情。

2 个回答

7

我用的是这种方法:

import datetime
import logging
import re
import urllib

from google.appengine.ext import blobstore
from google.appengine.ext import db
from google.appengine.ext import webapp

from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template

from google.appengine.api import taskqueue
from google.appengine.api import users


class IndexHandler(webapp.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write('Hello. Blobstore is being purged.\n\n')
        try:
            query = blobstore.BlobInfo.all()

            index = 0

            to_delete = []
            blobs = query.fetch(400)
            if len(blobs) > 0:
                for blob in blobs:
                    blob.delete()
                    index += 1

            hour = datetime.datetime.now().time().hour
            minute = datetime.datetime.now().time().minute
            second = datetime.datetime.now().time().second
            self.response.out.write(str(index) + ' items deleted at ' + str(hour) + ':' + str(minute) + ':' + str(second))
            if index == 400:
                self.redirect("/purge")

        except Exception, e:
            self.response.out.write('Error is: ' + repr(e) + '\n')
            pass

APP = webapp.WSGIApplication(
    [
        ('/purge', IndexHandler),
    ],
    debug=True)

def main():
    util.run_wsgi_app(APP)


if __name__ == '__main__':
    main()

根据我的经验,一次处理超过400个数据块会失败,所以我每处理400个就让它重新加载一次。我试过用 blobstore.delete(query.fetch(400)) 来删除,但我觉得现在有个bug。什么都没发生,也没有被删除。

4

你把查询对象传给了删除方法,这样它会分批次地获取数据,然后一次性提交一个巨大的删除请求。这种做法效率很低,因为需要多次获取数据,而且如果结果太多,超出了可用的时间或内存,就会出问题。这个任务要么一次性完成,不需要再连接其他任务,要么很可能会反复失败,因为它无法一次性获取所有的数据。

另外,调用 count 方法会执行查询来计算结果数量,这样做很浪费时间,因为你反正还要获取结果。

更好的做法是使用 fetch 方法分批获取结果,然后逐批删除。可以使用游标来设置下一批数据,避免查询需要遍历所有的“已删除”记录才能找到第一个有效的记录。理想情况下,可以每个任务删除多个批次,并使用定时器来判断何时停止,然后连接下一个任务。

撰写回答