আমরা আমাদের প্রাইমারি PostgreSQL ডাটাবেসে পার্টিশन्ड টেবিল ব্যবহার করি পুরনো ডেটা দক্ষতার সাথে এক্সপায়ার করার জন্য, কারণ একটি বিশাল টেবিল থেকে প্রচুর ডেটা ডিলিট করলে ডাটাবেস পারফরম্যান্স ভুগতে পারে। ভার্সন ১০-এর আগে, PostgreSQL-এ পার্টিশन्ड টেবিলের নেটিভ সাপোর্ট ছিল না, তাই আমরা pg_partman এক্সটেনশন ব্যবহার করতাম পার্টিশনিং ইমপ্লিমেন্ট করার জন্য। এটি PostgreSQL-এর টেবিল ইনহেরিটেন্স ব্যবহার করে প্যারেন্ট টেবিলের চাইল্ড টেবিল তৈরি করে এবং ট্রিগার ব্যবহার করে ডেটা প্যারেন্ট টেবিলের বদলে চাইল্ড টেবিলে ইনসার্ট করে। এক্সটেনশনটি ভালো কাজ করত, কিন্তু এর একটি ডাউনসাইড ছিল — এটি Amazon RDS-এ অপশন নয়, কারণ সাপোর্টেড নয়। এখন PostgreSQL-এ নেটিভ পার্টিশন সাপোর্ট আছে, তাই আমি চিন্তা করলাম এক্সটেনশনটি ড্রপ করার সময় হয়েছে যাতে RDS ব্যবহার করার অপশন থাকে।
আমাদের পার্টিশনিং ইউজ-কেসverhältনামূলক সিম্পল: আমরা টেবিল পার্টিশন করি টাইম বেসড, প্রতিটি দিন, সপ্তাহ, বা মাসে একটি নতুন পার্টিশন তৈরি করে, এভাবেই কত রো সব পার্টিশনে স্টোর করতে চাই এবং কতদিন ডেটা রিটেইন করতে চাই সেটির উপর নির্ভর করে। আমাদের সব পার্টিশन्ड টেবিলে একটি created_at কলাম থাকে যা রোটি কোন পার্টিশনে স্টোর হবে সেটি নির্ধারণ করবে। উদাহরণস্বরূপ, আমাদের একটি টেবিল হতে পারে এরকম:
create table events (
project_id integer,
data jsonb,
created_at timestamp
) partition by range (created_at);
আমরা যদি সাপ্তাহিক পার্টিশন চাই, তবে সেগুলো এরকম দেখাবে:
create table events_p2019_10_28 partition of events for values from ('2019-10-28') to ('2019-11-04');
create table events_p2019_11_04 partition of events for values from ('2019-11-04') to ('2019-11-11');
টাইম-বেসড পার্টিশনিং স্কিমে, পুরনো ডেটা ডিলিট করা খুব সহজ — শুধু একটি পার্টিশন ড্রপ করলেই চলে। রेгуলার মেইনটেন্যান্স যা আমাদের করতে হয়, সেটি হচ্ছে ডেট রেঞ্জের জন্য নতুন পার্টিশন তৈরি করা যেমন আমরা তাদের কাছে যাচ্ছি এবং পুরনো পার্টিশন ডিলিট করা যেগুলোতে আমরা আর ডেটা রাখতে চাই না। এই মেইনটেন্যান্স একটু সহজ করার জন্য, আমি pg_partition_manager gem তৈরি করলাম। স্বাভাবিকভাবেই, এটি pg_partman এক্সটেনশনের সাথে আমার অভিজ্ঞতা থেকে অনুপ্রাণিত যেটি আমাদের খুব ভালো সার্ভিস দিয়েছে।
উপরের events টেবিল এবং পার্টিশনিং স্কিম দেওয়া থাকলে, আপনি কীভাবে এই জেমটি ব্যবহার করবেন সেটি দেখি। আপনি একটি স্ক্রিপ্ট বা রেক টাস্ক তৈরি করবেন এরকম:
require "pg_partition_manager"
PgPartitionManager::Time.process([{parent_table: "public.events", period: "week", premake: 1, retain: 3}])
parent_table ডিফাইন করা হয় schema.table_name হিসেবে (public, ডিফল্ট স্কিমা, প্রায়শই Rails ডেভেলপাররা একমাত্র ব্যবহার করে)। period হতে পারে day, week, বা month। আপনি বেছে নিতে পারেন কত টেবিল এডভান্সে তৈরি করবেন (কারেন্ট পিরিয়ডের পর) premake দিয়ে, এবং কত টেবিল রাখবেন (কারেন্ট পিরিয়ডের আগে) retain দিয়ে। জেম ডিফল্টলি ৪ টেবিল প্রি-ক্রিয়েট করে যদি আপনি premake স্পেসিফাই না করেন, এবং ডিফল্টলি ৭ দিন, ৪ সপ্তাহ, এবং ৬ মাস ডেটা রিটেইন করে যদি আপনি retain স্পেসিফাই না করেন।
এই স্ক্রিপ্ট/টাস্ককে ডেইলি ক্রন জব দিয়ে ইনভোক করুন, এবং আপনি সেট — এটি প্রয়োজন অনুযায়ী টেবিল তৈরি এবং ড্রপ করবে।
সকল ActiveRecord কোয়েরি নন-পার্টিশन्ड টেবিলের মতোই কাজ করে, তাই আপনার কোডে কিছু চেঞ্জ করার প্রয়োজন নেই। অর্থাৎ, Event.create, Event.where, ইত্যাদি যেন আগে কাজ করত, ঠিক একইভাবে কাজ করবে, PostgreSQL ডেটা ইনসার্ট করার সময় সঠিক পার্টিশনে রাখবে। একটি পরিবর্তন আপনি লক্ষ্য করতে পারেন যদি আপনার অনেক ডেটা থাকে... যখন আপনি created_at আপনার কোয়েরিতে ইনক্লুড করবেন, PostgreSQL সকল পার্টিশন স্ক্যান করবে না — শুধু যেসব পার্টিশন আপনার where ক্লজে সপেকিফাইড রেঞ্জ কভার করে সেগুলো।
সংক্ষেপে, আপনার কাছে অনেক টাইম-বেসড ডেটা আছে যা এক্সপায়ার হলে ডিলিট করতে চান, তবে PostgreSQL পার্টিশन्ड টেবিল এবং pg_partition_manager gem ব্যবহার করে আপনার অ্যাপকে খুশি রাখুন। :)