Tworzę nową tabelę, która musi zostać wypełniona danymi opartymi na kontach użytkowników (powyżej kilkudziesięciu tysięcy) z następującym jednorazowym zadaniem rake.Jak powinieneś wypełnić nową tabelę w Railsach?
To, co postanowiłem zrobić, to stworzyć duży łańcuch INSERT dla każdych 2000 użytkowników i wykonać to zapytanie.
Oto co kod z grubsza wygląda tak:
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
Więc zastanawiam się, czy istnieje lepszy sposób to zrobić? Jakie są wady podejścia, które podjąłem? Jak mam to poprawić? Co się stanie, jeśli nie podzielę tablicy inserts
i nie wykonam pojedynczego INSERT
z kilkoma tysiącami krotek VALUES? Jakie są wady tej metody?
Dzięki!
Dlaczego nie używałbyś metod MyNewTable zawiniętych w transakcję, aby przyspieszyć wstawianie? Obecna implementacja otwiera Cię na SQL injection. –
Och, brakowało mi, że robisz wiele wkładek naraz. Byłoby to rzeczywiście szybsze (ale nie pewne, ile zawinąłeś normalne wkładki w transakcję o wartości 1000. –