درج های یک به یک را متوقف کنید! داده های فله در ریل با insert_all یا activeRecord-import

اگر واردات CSV شما نسبت به اینترنت شماره گیری کندتر است ، کشف کنید که چگونه درج های فله ای می توانند عملکرد ریل های شما را موشک کنند. 🐢
1. چرا درج فله ماده؟
به عنوان مثال هنگام برخورد با مجموعه داده های بزرگ ، می خواهید یک CSV حاوی بیش از هزار کار از بخش خود وارد کنید و سوابق را یک به یک وارد کنید (.create
یا .save
)) عملکرد را به شدت کاهش دهید و علت تنگناهای پایگاه داده
تصور کنید درج کنید 100000 رکورد– انجام آن به طور سنتی به معنی است 100،000 پرس و جو جداگانه! در عوض ، درج فله این را به a کاهش می دهد پرس و جو کارآمد، صرفه جویی در وقت و منابع.
2. پیش نیازها
قبل از غواصی ، اطمینان حاصل کنید:
- شما استفاده می کنید ریل 6+ برای
insert_all
- شما
activerecord-import
گوه در صورت استفاده از نسخه قدیمی که از ریل های 3.x پشتیبانی می کند نصب شده است
3. راهنمای گام به گام
3.1 مشکل درج هر یک از آنها
به عنوان مثال ، شما می خواهید 100K سوابق کارها را با روشی ساده لوحانه ایجاد کنید ، اینگونه به نظر می رسد:
# Create 100k records each times
100_000.times do |i|
Task.create!({ name: "Task #{i}", description: "This is description of task #{i}", is_finished: false })
end
من با این قطعه معیار را در اینجا انجام دادم:
execution_time = Benchmark.measure do
100_000.times do |i|
Task.create!({ name: "Task #{i}", description: "This is description of task #{i}", is_finished: false })
end
end
puts "Execution time: #{execution_time.real} seconds"
تصویر نشان می دهد که اجرای ایجاد ضبط طول می کشد 20.99 ثانیه
✅ جوانب مثبت:
-
اعتبار سنجی مدل ها یا تماس های تماس تلفنی کار می کند جدید
the name field is not null but there is a call with null name, the insert will be raise with errors
- نسخه های قدیمی ریل <6.0 پشتیبانی – پروژه میراث بدون پشتیبانی فله.
❌ منفی:
- مسئله عملکرد – هر درج به یک معامله پایگاه داده جداگانه نیاز دارد و سربار افزایش می یابد.
- افزایش ترافیک شبکه – درخواست 100K در پایگاه داده ایجاد می شود که باعث افزایش هزینه های شبکه می شود.
3.2 راه حل 1: استفاده کنید insert_all
در insert_all
روش به شما امکان می دهد تا وارد شوید سوابق متعدد به طور همزمان، عملکرد قابل توجهی را افزایش می دهد.
نمونه: با استفاده از insert_all
برای ایجاد وظایف 100K
tasks = []
# Initialize 100k tasks hash then add to tasks array
100_000.times do |i|
tasks << { name: "Task #{i}", description: "This is description of task #{i}", is_finished: false }
end
# Bulk insert all the initialized tasks
Task.insert_all(tasks)
✅ جوانب مثبت:
-
سریعتر از
.create
– پرس و جو مجرد SQL - روش داخلی ریل – عملیات فله به طور مستقیم در ریل بدون سنگهای اضافی.
❌ منفی:
- مدل های ActiveRecord را قبول نمی کند – فقط با هش های خام کار می کند.
- اعتبار سنجی مدل و تماس های برگشتی – یکپارچگی داده ها باید به صورت دستی انجام شود.
- نمی تواند به طور خودکار انجمن ها را اداره کند – برای واکشی شناسه های مرتبط به پرس و جوهای اضافی نیاز دارد.
نمونه: درج Tasks
که متعلق به Department
departments = [{ name: "Marketing" }]
department = Department.insert_all(departments)
department_id = department.id # Error raised
tasks = [{ name: "Task 0", description: "This is the task description", is_finished: false, department_id: ??? }] # missing department_id here
تصویر نشان می دهد که پس از استفاده نمی توان هیچ شناسه ای را بازگرداند insert_all
👉 ثابت کردن: بازیابی دستی department_id
قبل از درج tasks
با اضافه کردن یک پرس و جو اضافی.
department = Department.find_by(name: "Marketing") # cost a SQL query
tasks = [{ name: "Task 0", description: "This is the task description", is_finished: false, department_id: department.id }]
3.3 راه حل 2: بهترین از هر دو جهان – استفاده کنید activerecord-import
گوه
در import
روش به شما امکان می دهد مدل هایی را با انجمن ها وارد کنید
نمونه: با استفاده از import
برای ایجاد 100K وظایف در 1 بخش
department = Department.new(name: "Marketing")
tasks = []
100_000.times do |i|
tasks << Task.new({ name: "Task #{i}", description: "This is description of task #{i}", is_finished: false })
end
department.tasks = tasks
execution_time = Benchmark.measure do
Department.import [department]
end
puts "Execution time: #{execution_time.real} seconds"
✅ جوانب مثبت:
- با ستون های خام و آرایه های مقادیر (سریعترین) کار می کند
- با اشیاء مدل کار می کند (سریعتر)
- اعتبارسنجی ها را انجام می دهد (سریع)
- به روزرسانی های کلید تکراری (به MySQL ، SQLITE 3.24.0+ یا Postgres 9.5+ نیاز دارد)
❌ منفی:
- به یک گوهر اضافی نصب شده نیاز دارید
- تماسهای برگشتی ActiveRecord مربوط به ایجاد ، به روزرسانی یا از بین بردن سوابق (غیر از
before_validation
وتafter_validation
) هنگام فراخوانی روش واردات فراخوانی نمی شود. (تماس جداگانه باrun_callbacks
همانطور که توصیه می شود)
4. نتیجه گیری
یک قانون برای یادآوری هنگام درج تعداد زیادی از سوابق (به عنوان مثال: وارد کردن تعداد زیادی از سوابق از یک پرونده CSV) این است که از ایجاد سوابق یک به یک جلوگیری کنید. در عوض ، ما می توانیم استفاده را در نظر بگیریم activerecord-import
یا insert_all
برای یک عملکرد عالی
5 مرجع