【问题标题】:What is the most efficient way to write 3GB of data to datastore?将 3GB 数据写入数据存储的最有效方法是什么?
【发布时间】:2014-11-13 19:45:30
【问题描述】:

我有一个 3Gb 的 csv 文件。我想将所有数据写入 GAE 数据存储。我尝试逐行读取文件,然后将数据发布到我的应用程序,但我只能创建大约 1000 个新实体,然后才能超过免费层并开始产生相当高的成本。将此数据上传到数据存储区的最有效/最具成本效益的方法是什么?

【问题讨论】:

    标签: python-2.7 google-app-engine google-cloud-datastore


    【解决方案1】:

    如果您需要将每一行存储为单独的实体,那么如何创建这些实体并不重要 - 您可以通过批处理请求来提高性能,但不会影响成本。

    成本取决于您在每个实体中拥有多少索引属性。确保只对需要索引的属性进行索引。

    【讨论】:

    • 感谢您的回答。需要创建超过 1900 万个实体,每个实体有 16 个属性。我相信这将意味着对数据存储进行 2 x 19M 调用(每次写入 2 次),并且从这个链接 (cloud.google.com/appengine/pricing) 调用将花费 (38M / 100k * $0.06 = $22.80)?问题是写入约 1000 个新实体正在用完免费配额 (50k) - 每个实体的写入量要多于 2 次。
    • 正如我所提到的,每个索引属性还有 2 次写入操作。除非您将所有 16 个属性都标记为未编入索引,否则您的成本将是每个实体 34 次写入,而不是 2 次。
    • 哇!我误解了 - 我认为只有在 index.yaml 中创建了显式索引时才会对属性进行索引。因此,将其写入数据存储区的成本(忽略免费配额)约为 364 美元。
    【解决方案2】:

    最好的办法是使用映射器。都是一个文件吗?如果是这样,可以将其分解为尽可能多的小文件,然后使用映射器填充数据库。分解它们的原因是映射器将每个文件发送到它自己的线程。因此,文件越多,您拥有的线程越多,它完成工作的速度就越快。

    阅读GCSMapreduce 了解更多信息

    类 MainPage(webapp2.RequestHandler):

    def get(self):
        bucketName = "" #Bucketname
        listOfFiles = gcs.listbucket("/" + bucketName + "path to folder with the files")
    
        pipeline = Mapreduce(bucketName, listOfFiles)
        pipeline.start()
        self.redirect(pipeline.base_path + "/status?root=" + pipeline.pipeline_id)
    
    class Mapreduce(base_handler.PipelineBase):
        def run(self, bucketName, listOfFiles):
            yield mapper_pipeline.MapperPipeline(
                "Fill Data",
                "main.FillDB",
                "mapreduce.input_readers._GoogleCloudStorageInputReader",
                params = {"input_reader" : {
                                     "bucket_name" : bucketName,
                                     "objects" : listOfFiles
                                     }                                 
                                 },
    
                shards=64)
    
    def FillDB(data):
        for line in data:
            infoForDb = line.split(",")
            inputDB = EntityName(id=infoForDb[0], productName=infoForDb[1])
            db.put(inputDB)
        return
    

    【讨论】:

    • 问题在于成本,而不是速度。
    • OP 也提到了高效。使用 MapReduce 是一种将数据迁移到数据存储区的好方法。
    猜你喜欢
    • 1970-01-01
    • 2017-01-12
    • 2010-09-24
    • 2011-06-07
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多