【发布时间】:2011-01-06 07:12:35
【问题描述】:
让我做个准备:我的应用程序处理礼品卡。当我们创建卡片时,它们必须有一个唯一的字符串,用户可以使用它来兑换它。因此,当有人像零售商一样订购我们的礼品卡时,我们需要制作大量新的卡片对象并将它们存储在数据库中。
考虑到这一点,我想看看我的应用程序生成 100,000 张卡片的速度有多快。数据库专家,我不是,所以我需要有人解释一下这个小现象:当我创建 1000 张卡片时,需要 5 秒。当我创建 100,000 张卡片时,应该需要 500 秒吧?
现在我知道你想看到什么,我正在使用的卡片创建方法,因为第一个假设是它会越来越慢,因为它正在检查一堆卡片的唯一性,随着它的进行越来越多。但我可以告诉你我的 rake 任务
desc "Creates cards for a retailer"
task :order_cards, [:number_of_cards, :value, :retailer_name] => :environment do |t, args|
t = Time.now
puts "Searching for retailer"
@retailer = Retailer.find_by_name(args[:retailer_name])
puts "Retailer found"
puts "Generating codes"
value = args[:value].to_i
number_of_cards = args[:number_of_cards].to_i
codes = []
top_off_codes(codes, number_of_cards)
while codes != codes.uniq
codes.uniq!
top_off_codes(codes, number_of_cards)
end
stored_codes = Card.all.collect do |c|
c.code
end
while codes != (codes - stored_codes)
codes -= stored_codes
top_off_codes(codes, number_of_cards)
end
puts "Codes are unique and generated"
puts "Creating bundle"
@bundle = @retailer.bundles.create!(:value => value)
puts "Bundle created"
puts "Creating cards"
@bundle.transaction do
codes.each do |code|
@bundle.cards.create!(:code => code)
end
end
puts "Cards generated in #{Time.now - t}s"
end
def top_off_codes(codes, intended_number)
(intended_number - codes.size).times do
codes << ReadableRandom.get(CODE_LENGTH)
end
end
我正在使用一个名为 readable_random 的 gem 作为唯一代码。因此,如果您通读所有这些代码,您会发现它在开始创建卡片之前已经完成了所有的唯一性测试。它还在运行时将状态更新写入屏幕,并且它总是在创建时坐一会儿。同时,它通过了唯一性测试。所以我对 stackoverflow 社区的问题是:为什么我的数据库随着我添加更多卡片而变慢?为什么这不是关于每张卡时间的线性函数?我确信答案很简单,我只是一个对数据存储一无所知的白痴。如果有人有任何建议,您将如何优化此方法,您认为创建 100,000 张卡片的速度有多快?
(当我在图表上绘制我的时间并快速拟合曲线以获得我的直线公式时,我计算了使用我当前的代码创建 100,000 张卡片需要多长时间,结果显示为 5.5 小时。这可能完全错误,我不确定。但如果它保持在我拟合的曲线上,它就在附近。)
【问题讨论】:
-
你试过没有交易吗?
-
在我知道交易存在之前,我只是在没有交易块的情况下创建它们。交易加快了进程。
标签: ruby database optimization activerecord ruby-on-rails-3