5

Aşağıdaki bir kerelik komisyon göreviyle Kullanıcı hesaplarına (birkaç düzineden fazla bin) dayanan verilerle doldurulması gereken yeni bir tablo oluşturuyorum.Rails'de yeni bir tabloyu nasıl doldurmalısınız?

Yapmaya karar verdiğim her 2000 kullanıcı için büyük bir INSERT dizesi oluşturmak ve bu sorguyu yürütmek. Bunu yapmak için daha iyi bir yol yoktur,

task :backfill_my_new_table => :environment do 
    inserts = [] 
    User.find_each do |user| 
     tuple = # form the tuple based on user and user associations like (1, 'foo', 'bar', NULL) 
     inserts << tuple 
    end 

    # At this point, the inserts array is of size at least 20,000 
    conn = ActiveRecord::Base.connection 
    inserts.each_slice(2000) do |slice| 
     sql = "INSERT INTO my_new_table (ref_id, column_a, column_b, column_c) VALUES #{inserts.join(", ")}" 
     conn.execute(sql) 
    end 
end 

Yani, merak ediyorum:

İşte kod kabaca böyle görünüyor? Aldığım yaklaşımın bazı dezavantajları nelerdir? Bunu nasıl geliştirmeliyim? inserts dizisini dilimlemediysem ve sadece bir çift düzine bin VALUES tupleli tek bir INSERT uyguladıysam ne olur? Bu yöntemin sakıncaları nelerdir?

Teşekkürler!

+0

Neden ekleri hızlandırmak için bir işlemde sarılmış MyNewTable yöntemlerini kullanmıyorsunuz? Ayrıca, mevcut uygulama sizi SQL enjeksiyonuna açar. –

+0

Oh, bir kerede birden çok ekleme yaptığınızı kaçırdım. Bu gerçekten daha hızlı olacaktır (ancak her biri 1000 kelimelik bir işlemde normal ekler eklediğinizde ne kadar emin olacağınızdan emin olamazsınız. –

cevap

0

hangi PG sürümünü kullandığınız, ancak bir tabloya toplu yükleme verilerinin çoğu durumda bu yeterli bir denetim listesi aşağıda bağlıdır:

  • deneyin yerine INSERT mümkünse ait COPY kullanmak;
  • , çok sayıda ekleme kullanılıyorsa, AutoCommit devre dışı bırakmak ve tek bir işlemde tüm eklemeler sarmak yani BEGIN; INSERT ...; INSERT ...; COMMIT;
  • bir hedef tablo/'üzerine
  • devre dışı endeksler ve kontrol/kısıtlamalar;
  • tablo tetikleyicilerini devre dışı bırakın;
  • alter table
  • yüzden unlogged (PG 9.5 beri, verilerin aktarılmasından sonra oturum açmak için unutmayın) veya artırmak oldu max_wal_size böylece alışkanlık satır

20k için bu kadar büyük bir anlaşma değil sular altında WAL Bir PG, bir işlem içinde çok 2k dilimli ekler bazı çok karmaşık tetikleyiciler/kontroller dahil olmadıkça, sadece iyi olacaktır. PG manual section on bulk loading da okunmaya değer.

UDP: ve a little bit old, yet wonderful piece from depesz, alıntı:

öyleyse, mümkün olduğunca hızlı veri eklemek istiyorsanız - kullanım kopyası (- pgbulkload daha iyisi ya). Herhangi bir sebepten dolayı kopya kullanamazsanız, çok satırlı ekleri kullanın (8.2'de yeni!). eğer yapabilirseniz, bunları işlemlere dahil edin ve hazırlanmış işlemleri kullanın, ancak genellikle - size fazla vermezler.