برنامه نویسی

درج های یک به یک را متوقف کنید! داده های فله در ریل با 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 ثانیه

✅ جوانب مثبت:

  1. اعتبار سنجی مدل ها یا تماس های تماس تلفنی کار می کند جدید the name field is not null but there is a call with null name, the insert will be raise with errors
  2. نسخه های قدیمی ریل <6.0 پشتیبانی – پروژه میراث بدون پشتیبانی فله.

❌ منفی:

  1. مسئله عملکرد – هر درج به یک معامله پایگاه داده جداگانه نیاز دارد و سربار افزایش می یابد.
  2. افزایش ترافیک شبکه – درخواست 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)
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

همه را وارد کنید

✅ جوانب مثبت:

  1. سریعتر از .create – پرس و جو مجرد SQL
  2. روش داخلی ریل – عملیات فله به طور مستقیم در ریل بدون سنگهای اضافی.

❌ منفی:

  1. مدل های ActiveRecord را قبول نمی کند – فقط با هش های خام کار می کند.
  2. اعتبار سنجی مدل و تماس های برگشتی – یکپارچگی داده ها باید به صورت دستی انجام شود.
  3. نمی تواند به طور خودکار انجمن ها را اداره کند – برای واکشی شناسه های مرتبط به پرس و جوهای اضافی نیاز دارد.

نمونه: درج 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"
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

معیار activeRecord-import

✅ جوانب مثبت:

  • با ستون های خام و آرایه های مقادیر (سریعترین) کار می کند
  • با اشیاء مدل کار می کند (سریعتر)
  • اعتبارسنجی ها را انجام می دهد (سریع)
  • به روزرسانی های کلید تکراری (به MySQL ، SQLITE 3.24.0+ یا Postgres 9.5+ نیاز دارد)

❌ منفی:

  • به یک گوهر اضافی نصب شده نیاز دارید
  • تماسهای برگشتی ActiveRecord مربوط به ایجاد ، به روزرسانی یا از بین بردن سوابق (غیر از before_validation وت after_validation) هنگام فراخوانی روش واردات فراخوانی نمی شود. (تماس جداگانه با run_callbacks همانطور که توصیه می شود)

4. نتیجه گیری

یک قانون برای یادآوری هنگام درج تعداد زیادی از سوابق (به عنوان مثال: وارد کردن تعداد زیادی از سوابق از یک پرونده CSV) این است که از ایجاد سوابق یک به یک جلوگیری کنید. در عوض ، ما می توانیم استفاده را در نظر بگیریم activerecord-import یا insert_all برای یک عملکرد عالی

5 مرجع

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا