刚刚开始使用Kiba,没有找到任何明显的,但我可能只是引导我内心的孩子(通过盯着天花板寻找他们的鞋子)。
我想将一个非常大的表转储到Amazon Redshift。似乎最快的方法是将一堆CSV文件写入S3存储桶,然后告诉Redshift(通过COPY
命令)将它们拉入。神奇的缩放gremlins将完成其余工作。 / p>
所以,我认为我希望Kiba为每10k行数据写一个CSV文件,然后将其推送到s3,然后开始写入新文件。最后,对COPY
那么,我可以“管道”工作还是应该是一个大的嵌套的Destination类?
即
source -> transform -> transform ... -> [ csv -> s3 ]{every 10000}; post-process
答案 0 :(得分:0)
我不确定这里的确切问题。但是,我认为你的解决方案似乎总体上是正确的,但很少有建议。
gzip
个记录。menifest
创建,然后运行copy
命令提供menifest
文件作为输入。答案 1 :(得分:0)
Kiba作者在这里。谢谢你试试吧!
目前,实现此目标的最佳方法是创建我称之为“缓冲目的地”的内容。 (其中一个版本很可能会在Kiba Common中结束)。
(请彻底测试一下,我今天早上为你写了这篇文章,虽然我过去使用的通用版本较少,但我还没有运行它。同时请记住这一点版本为你的10k行使用内存缓冲区,所以将数字增加到更大的数据会消耗内存。但是也可以创建最少内存消耗的版本,这会在你获得它们时将行写入文件)
class BufferingDestination
def initialize(buffer_size:, on_flush:)
@buffer = []
@buffer_size
@on_flush = on_flush
@batch_index = 0
end
def write(row)
@buffer << row
flush if @buffer.size >= buffer_size
end
def flush
on_flush.call(batch_index: @batch_index, rows: @buffer)
@batch_index += 1
@buffer.clear
end
def close
flush
end
end
这是你可以像这样使用的东西,例如这里重用Kiba Common CSV destination(尽管你也可以写自己的):
require 'kiba-common/destinations/csv'
destination BufferingDestination,
buffer_size: 10_000,
on_flush: -> { |batch_index, rows|
filename = File.join("output-#{sprintf("%08d", batch_index)}")
csv = Kiba::Common::Destinations::CSV.new(
filename: filename,
csv_options: { ... },
headers: %w(my fields here)
)
rows.each { |r| csv.write(r) }
csv.close
}
然后,您可以在生成文件后触发COPY
块中的on_flush
权限(如果您希望立即开始上传),或者在post_process
块中触发hostContains
只有在所有CSV准备就绪后才会启动,如果您愿意,这可以是确保某种形式的交易全局上传的功能。
如果你确实需要这个(但是请小心使用僵尸线程等),你可能会想象并开始一个线程队列以实际并行处理上传。
另一种方法是采取多个步骤&#34; ETL流程,其中一个脚本用于生成CSV,另一个脚本用于上传,同时运行(例如我在RubyKaigi 2018的演讲中解释过这一点)。
让我知道事情对你有用!
答案 2 :(得分:0)
Thibaut,我做了类似的事情,除了我将它流式传输到Tempfile,我认为......
require 'csv'
# @param limit [Integer, 1_000] Number of rows per csv file
# @param callback [Proc] Proc taking one argument [CSV/io], that can be used after
# each csv file is finished
module PacerPro
class CSVDestination
def initialize(limit: 1_000, callback: ->(obj) { })
@limit = limit
@callback = callback
@csv = nil
@row_count = 0
end
# @param row [Hash] returned from transforms
def write(row)
csv << row.values
@row_count += 1
return if row_count < limit
self.close
end
# Called by Kiba when the transform pipeline is finished
def close
csv.close
callback.call(csv)
tempfile.unlink
@csv = nil
@row_count = 0
end
private
attr_reader :limit, :callback
attr_reader :row_count, :tempfile
def csv
@csv ||= begin
@tempfile = Tempfile.new('csv')
CSV.open(@tempfile, 'w')
end
end
end
end