当前位置:  开发笔记 > 编程语言 > 正文

删除Google App Engine中的所有数据

如何解决《删除GoogleAppEngine中的所有数据》经验,为你挑选了8个好方法。

我想在Google App Engine中删除特定类型的所有数据.做这个的最好方式是什么?我写了一个删除脚本(hack),但是因为有这么多的数据是在几百条记录之后超时.



1> 小智..:

我目前正在按键删除实体,而且似乎更快.

from google.appengine.ext import db

class bulkdelete(webapp.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        try:
            while True:
                q = db.GqlQuery("SELECT __key__ FROM MyModel")
                assert q.count()
                db.delete(q.fetch(200))
                time.sleep(0.5)
        except Exception, e:
            self.response.out.write(repr(e)+'\n')
            pass

从终端,我运行curl -N http:// ...



2> Pieter Herro..:

您现在可以使用数据存储区管理员:https://developers.google.com/appengine/docs/adminconsole/datastoreadmin#Deleting_Entities_in_Bulk



3> 小智..:

如果我是一个偏执狂的人,我会说谷歌应用引擎(GAE)并没有让我们想要删除数据.我将跳过关于索引大小的讨论,以及它们如何将6 GB的数据转换为35 GB的存储空间(需要付费).这是另一个故事,但他们确实有办法解决这个问题 - 限制数量的属性来创建索引(自动生成的索引)等等.

我决定写这篇文章的原因是我需要在沙盒中"核对"我的所有种类.我读到了它,最后想出了这段代码:

package com.intillium.formshnuker;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;

import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.appengine.api.labs.taskqueue.TaskOptions.Method;

import static com.google.appengine.api.labs.taskqueue.TaskOptions.Builder.url;

@SuppressWarnings("serial")
public class FormsnukerServlet extends HttpServlet {

 public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {

  response.setContentType("text/plain");

  final String kind = request.getParameter("kind");
  final String passcode = request.getParameter("passcode");

  if (kind == null) {
   throw new NullPointerException();
  }

  if (passcode == null) {
   throw new NullPointerException();
  }

  if (!passcode.equals("LONGSECRETCODE")) {
   response.getWriter().println("BAD PASSCODE!");
   return;
  }

  System.err.println("*** deleting entities form " + kind);

  final long start = System.currentTimeMillis();

  int deleted_count = 0;
  boolean is_finished = false;

  final DatastoreService dss = DatastoreServiceFactory.getDatastoreService();

  while (System.currentTimeMillis() - start < 16384) {

   final Query query = new Query(kind);

   query.setKeysOnly();

   final ArrayList keys = new ArrayList();

   for (final Entity entity: dss.prepare(query).asIterable(FetchOptions.Builder.withLimit(128))) {
    keys.add(entity.getKey());
   }

   keys.trimToSize();

   if (keys.size() == 0) {
    is_finished = true;
    break;
   }

   while (System.currentTimeMillis() - start < 16384) {

    try {

     dss.delete(keys);

     deleted_count += keys.size();

     break;

    } catch (Throwable ignore) {

     continue;

    }

   }

  }

  System.err.println("*** deleted " + deleted_count + " entities form " + kind);

  if (is_finished) {

   System.err.println("*** deletion job for " + kind + " is completed.");

  } else {

   final int taskcount;

   final String tcs = request.getParameter("taskcount");

   if (tcs == null) {
    taskcount = 0;
   } else {
    taskcount = Integer.parseInt(tcs) + 1;
   }

   QueueFactory.getDefaultQueue().add(
    url("/formsnuker?kind=" + kind + "&passcode=LONGSECRETCODE&taskcount=" + taskcount).method(Method.GET));

   System.err.println("*** deletion task # " + taskcount + " for " + kind + " is queued.");

  }

  response.getWriter().println("OK");

 }

}

我有超过600万条记录.好多啊.我不知道删除记录的成本是多少(可能更经济,不删除它们).另一种方法是请求删除整个应用程序(沙箱).但在大多数情况下,这是不现实的.

我决定使用较小的记录组(简单查询).我知道我可以去500个实体,但后来我开始收到很高的失败率(重新删除功能).

我从GAE团队的请求:请添加一项功能,以删除单个交易中的所有实体.



4> Jason Etheri..:

大概是你的黑客是这样的:

# Deleting all messages older than "earliest_date"
q = db.GqlQuery("SELECT * FROM Message WHERE create_date < :1", earliest_date)
results = q.fetch(1000)

while results:
    db.delete(results)
    results = q.fetch(1000, len(results))

如你所说,如果有足够的数据,你将在它通过所有记录之前达到请求超时.您必须多次从外部重新调用此请求以确保删除所有数据; 很容易做到,但几乎不理想.

管理控制台似乎没有提供任何帮助,因为(根据我自己的经验),它似乎只允许列出给定类型的实体,然后逐页删除.

在测试时,我不得不在启动时清除我的数据库以摆脱现有数据.

我可以从中推断出谷歌的运作原则是磁盘价格便宜,因此数据通常是孤立的(替换冗余数据的索引),而不是删除.鉴于目前每个应用程序都有固定数量的数据(0.5 GB),这对非Google App Engine用户没什么帮助.



5> Sam..:

尝试使用App Engine Console,您甚至不必部署任何特殊代码



6> 小智..:

我已经尝试过db.delete(结果)和App Engine Console,但它们似乎都不适合我.手动删除数据查看器中的条目(增加限制高达200)也不起作用,因为我上传了超过10000个条目.我结束了写这个剧本

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import wsgiref.handlers
from mainPage import YourData #replace this with your data
class CleanTable(webapp.RequestHandler):
    def get(self, param):
        txt = self.request.get('table')
        q = db.GqlQuery("SELECT * FROM "+txt)
        results = q.fetch(10)
        self.response.headers['Content-Type'] = 'text/plain'
        #replace yourapp and YouData your app info below.
        self.response.out.write("""
          
          
            """)

        try:
            for i in range(10):
                db.delete(results)
                results = q.fetch(10, len(results))
                self.response.out.write("

10 removed

") self.response.out.write(""" """) except Exception, ints: self.response.out.write(str(inst)) def main(): application = webapp.WSGIApplication([ ('/cleanTable(.*)', CleanTable), ]) wsgiref.handlers.CGIHandler().run(application)

诀窍是在html中包含重定向而不是使用self.redirect.我准备等到一夜之间摆脱我桌上的所有数据.希望GAE团队能够在将来更容易丢弃表格.



7> Alexander Ko..:

谷歌的官方回答是你必须删除分布在多个请求中的块.您可以使用AJAX,元刷新或从脚本请求您的URL,直到没有实体.



8> systempuntoo..:

在数据存储上处理批量删除的最快速有效的方法是使用最新的Google I/O上公布的新映射器API.

如果您选择的语言是Python,则只需在mapreduce.yaml文件中注册mapper 并定义如下函数:

from mapreduce import operation as op
def process(entity):
 yield op.db.Delete(entity)

在Java上你应该看看这篇文章,它建议这样的函数:

@Override
public void map(Key key, Entity value, Context context) {
    log.info("Adding key to deletion pool: " + key);
    DatastoreMutationPool mutationPool = this.getAppEngineContext(context)
            .getMutationPool();
    mutationPool.delete(value.getKey());
}


这是我使用的方法,虽然它非常占用CPU(不是数据存储CPU,通用CPU).
推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有