📍 ধানমন্ডি, ঢাকা-১২০৫🇬🇧 English

Oracle টেবিল Partitioning: বিলিয়ন-রো ERP টেবিল সামলানো

প্রতিটি বড় ERP সিস্টেম শেষ পর্যন্ত একই দেয়ালে গিয়ে ধাক্কা খায়: একটি sales, transaction বা audit টেবিল বেড়ে শত শত মিলিয়ন — তারপর বিলিয়ন — row-তে পৌঁছায়, আর যে query প্রথম বছরে তাৎক্ষণিক ছিল সেটিই এখন হামাগুড়ি দেয়। Partitioning হলো Oracle-এর সেই ফিচার যা এই সমস্যাটি সঠিকভাবে সমাধান করে। ঠিকভাবে করলে এটি একটি বিলিয়ন-রো টেবিলকে ছোট টেবিলের মতো অনুভব করায়, মাস-শেষের purge-কে এক-সেকেন্ডের metadata অপারেশনে পরিণত করে, আর বাকি টেবিলে হাত না দিয়েই ডেটা লোড করতে দেয়। ফার্মা sales history আর ERP fact টেবিলের জন্য partitioning ডিজাইন করার সময় আমি যে ব্যবহারিক গাইডটি অনুসরণ করি, এটি সেটাই।

১. Partitioning আসলে কী করে

Partitioning একটি লজিক্যাল টেবিলকে অনেকগুলো ফিজিক্যাল partition-এ ভাগ করে, প্রতিটি আলাদাভাবে সংরক্ষিত হয়, অথচ অ্যাপ্লিকেশন তখনও একটি একক টেবিলই দেখে। এর সুফল তিনটি:

  • পারফরম্যান্স — optimizer কেবল সেই partition-গুলোই পড়ে যেগুলোতে আপনার row থাকতে পারে (partition pruning)।
  • ব্যবস্থাপনাযোগ্যতা — একবারে এক partition করে ডেটা ব্যাকআপ, archive, compress বা drop করুন।
  • প্রাপ্যতা — একটি partition-এর রক্ষণাবেক্ষণ অন্যগুলোকে lock করে না।

২. একটি Partitioning কৌশল বেছে নেওয়া

  • Range — একটি ধারাবাহিক key দিয়ে, প্রায় সবসময়ই একটি তারিখ। time-series ERP ডেটার জন্য ডিফল্ট পছন্দ।
  • List — বিচ্ছিন্ন মান দিয়ে, যেমন region, branch বা company code।
  • Hash — যখন কোনো স্বাভাবিক range/list key নেই তখন সমবণ্টন; I/O ছড়িয়ে দিতে ভালো।
  • Composite — range-hash বা range-list, যেমন মাস অনুযায়ী partition, region অনুযায়ী sub-partition।

সোনালি নিয়ম: আপনার query যে column-এ filter করে সেই column-এ partition করুন। ৯০% query যদি transaction date দিয়ে সীমাবদ্ধ করে, তাহলে তারিখ দিয়ে partition করুন।

৩. তারিখ অনুযায়ী Range Partitioning — মূল কর্মঘোড়া

মাস অনুযায়ী partition করা একটি sales-history টেবিল:

CREATE TABLE sales_history (
  sale_id      NUMBER,
  sale_date    DATE,
  product_code VARCHAR2(20),
  territory    VARCHAR2(40),
  amount       NUMBER(14,2)
)
PARTITION BY RANGE (sale_date) (
  PARTITION p_2026_01 VALUES LESS THAN (DATE '2026-02-01'),
  PARTITION p_2026_02 VALUES LESS THAN (DATE '2026-03-01'),
  PARTITION p_2026_03 VALUES LESS THAN (DATE '2026-04-01')
);

৪. Interval Partitioning — হাতে হাতে Partition বানানো বন্ধ করুন

সাধারণ range partitioning-এর জ্বালা হলো, ডেটা আসার আগেই কাউকে পরের মাসের partition যোগ করতে হয় — ভুলে গেলে insert ব্যর্থ হয়। Interval partitioning Oracle-কে নতুন range-এ প্রথম insert হওয়ামাত্র আপনাআপনি partition বানাতে দেয়:

CREATE TABLE sales_history (
  sale_id   NUMBER,
  sale_date DATE,
  amount    NUMBER(14,2)
)
PARTITION BY RANGE (sale_date)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH')) (
  PARTITION p_start VALUES LESS THAN (DATE '2026-01-01')
);

জুলাই ২০২৭ তারিখের একটি row insert করুন, আর Oracle সেই মাসের partition আপনার জন্য বানিয়ে দেবে। এই একটি ফিচারই "table not extending" ধরনের রাত ২টার কল-এর একটি গোটা শ্রেণিকে নির্মূল করে দেয়।

৫. Partition Pruning — গতি যেখান থেকে আসে

এটাই তো পুরো ব্যাপার। একটি date filter দিয়ে Oracle পুরো টেবিল নয়, একটি partition পড়ে:

SELECT territory, SUM(amount)
FROM   sales_history
WHERE  sale_date >= DATE '2026-03-01'
AND    sale_date <  DATE '2026-04-01'
GROUP  BY territory;

plan-এ pruning নিশ্চিত করুন — একটি মাত্র partition দেখাচ্ছে এমন Pstart/Pstop খুঁজুন:

EXPLAIN PLAN FOR <your query>;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL,NULL,'PARTITION'));

Pstart/Pstop যদি পুরো range দেখায়, তাহলে আপনার query partition key-তে filter করছে না — query অথবা কৌশলটি ঠিক করুন।

৬. Local বনাম Global Index

  • Local index — টেবিলের মতোই একইভাবে partition করা। একটি table partition ড্রপ করলে তার index partition-ও সঙ্গে যায়। partitioned টেবিলের জন্য ডিফল্ট পছন্দ এবং রক্ষণাবেক্ষণের জন্য সবচেয়ে বন্ধুত্বপূর্ণ।
  • Global index — সব partition জুড়ে বিস্তৃত; যেসব query partition key অন্তর্ভুক্ত করে না তাদের জন্য ভালো (যেমন sale_id দিয়ে lookup)। খরচ: UPDATE INDEXES ব্যবহার না করলে partition রক্ষণাবেক্ষণ একে invalidate করে দিতে পারে।
CREATE INDEX sales_terr_lx ON sales_history(territory) LOCAL;
CREATE INDEX sales_id_gx   ON sales_history(sale_id) GLOBAL;

৭. Archiving ও Purging — এক-সেকেন্ডের Delete

বিলিয়ন-রো টেবিল থেকে এক মাসের ডেটা সাধারণ উপায়ে delete করলে বিশাল undo ও redo তৈরি হয় এবং ঘণ্টার পর ঘণ্টা লাগে। partitioning দিয়ে এটি তাৎক্ষণিক:

-- drop old data as pure metadata
ALTER TABLE sales_history DROP PARTITION p_2024_01 UPDATE INDEXES;

-- or move it to cheap storage / compress it first
ALTER TABLE sales_history MOVE PARTITION p_2024_01
  TABLESPACE archive_ts ROW STORE COMPRESS ADVANCED UPDATE INDEXES;

এভাবেই এমন একটি data-retention নীতি বাস্তবায়ন করবেন যা regulator ও storage বাজেট দুই-ই অনুমোদন করে।

৮. Partition Exchange — প্রায়-তাৎক্ষণিক Bulk Load

একটি live partitioned টেবিলে সরাসরি বড় batch লোড করা ধীর ও প্রতিযোগিতাপূর্ণ। বরং একটি আলাদা staging টেবিলে লোড করে সেটিকে metadata-only swap হিসেবে exchange করুন:

-- 1) load & index a plain staging table off to the side
-- 2) swap it into the partition instantly
ALTER TABLE sales_history
  EXCHANGE PARTITION p_2026_03
  WITH TABLE sales_stage
  INCLUDING INDEXES WITHOUT VALIDATION;

কোনো দীর্ঘ-চলা insert বা online query আটকানো ছাড়াই ডেটা সেকেন্ডের ভগ্নাংশে partitioned টেবিলে হাজির হয়।

৯. সাধারণ ফাঁদ

  • ভুল partition key — query যে column-এ filter করে না সেটিতে partition করলে সব overhead পাবেন, কিন্তু pruning-এর কিছুই না।
  • অতিরিক্ত ছোট partition — পাঁচ বছরের দৈনিক partition মানে ১,৮০০টি partition; dictionary ও parsing overhead জমে ওঠে। granularity-কে query ও retention প্যাটার্নের সঙ্গে মেলান।
  • Global index UNUSABLE রেখে দেওয়া — drop/exchange-এর পর UPDATE INDEXES ভুলে গেলে query ভেঙে পড়ে।
  • Hash partitioning-এ skew — সমবণ্টনের জন্য সবসময় hash partition-এর সংখ্যা দুইয়ের ঘাত (power of two) রাখুন।
  • বাসি statistics — incremental stats সংগ্রহ করুন যাতে কেবল পরিবর্তিত partition-গুলোই পুনরায় বিশ্লেষিত হয়।

১০. সেরা অনুশীলন

  • time-series ERP ডেটার জন্য interval সহ range-by-month — সেট করে ভুলে যান।
  • ডিফল্টে local index; global index যোগ করুন কেবল সেখানেই যেখানে non-key lookup দাবি করে।
  • বড় partitioned টেবিলে incremental statistics (INCREMENTAL = TRUE)।
  • retention নীতির অংশ হিসেবে পুরনো partition compress করুন এবং সস্তা storage-এ সরান।
  • load-এর জন্য exchangepurge-এর জন্য drop ব্যবহার করুন — দুটোই metadata অপারেশন।
  • নতুন কৌশল deploy করার পর DBMS_XPLAN দিয়ে সবসময় pruning যাচাই করুন

শেষ ভাবনা

একটি ERP ডেটাবেজ যেটি সুন্দরভাবে বয়সী হয়, আর যেটির পাঁচ বছরে জরুরি উদ্ধার লাগে — এ দুইয়ের পার্থক্যই হলো partitioning। ফিচারটি নিজে সরল; মূল্য থাকে ডিজাইন সিদ্ধান্তে — সঠিক key, সঠিক granularity, সঠিক index কৌশল। শুরুতেই এগুলো ঠিক করুন, তাহলে বছরের পর বছর ধারাবাহিক পারফরম্যান্স ও ব্যথাহীন ডেটা-জীবনচক্র ব্যবস্থাপনা কিনে নিতে পারবেন। আতঙ্কে পরে bolt-on করলে মাঝরাতে index rebuild করতে হবে।

আপনার যদি এমন একটি বড় টেবিল থাকে যা ধীর হয়ে যাচ্ছে, একটি retention নীতি বাস্তবায়ন করার থাকে, কিংবা একটি ERP fact টেবিলের partitioning ডিজাইন দরকার হয়, চলুন কথা বলি। ফার্মা ও ERP workload-এর জন্য আমি খুব বড় Oracle টেবিল partition ও tune করেছি এবং প্রথমবারেই সঠিক আকার দিতে সাহায্য করতে পারি।

🔗 একটি বিশাল টেবিল নিয়ে ভুগছেন?

Partitioning ডিজাইন, online conversion, index কৌশল ও retention নীতি। বিনামূল্যে ৩০-মিনিটের পরামর্শ।

📩 বিনামূল্যে পরামর্শ মূল্য দেখুন
নাসির উদ্দিন খান — Oracle DBA কনসালট্যান্ট

লেখক পরিচিতি

নাসির উদ্দিন খান সিনিয়র আইটি কনসালট্যান্ট · Oracle DBA · ERP ও AI বিশেষজ্ঞ OCP · Red Hat Certified · MBA · CSV · ১৮+ বছরের অভিজ্ঞতা

নাসির একজন Oracle Certified Professional এবং CSV-সার্টিফায়েড আইটি কনসালট্যান্ট, অবস্থান ঢাকা, বাংলাদেশ। ম্যানুফ্যাকচারিং, ফার্মা, ব্যাংকিং ও হেলথকেয়ার প্রতিষ্ঠানে Oracle ডেটাবেজ অ্যাডমিনিস্ট্রেশন (RAC, Data Guard, RMAN, VLDB partitioning), WebLogic middleware, ERP সিস্টেম ডিজাইন এবং AI ইন্টিগ্রেশন নিয়ে তাঁর ১৮+ বছরের হাতে-কলমে অভিজ্ঞতা রয়েছে।

তথ্যসূত্র ও আরও পড়ুন

এই গাইডটি বড় ERP ও ফার্মা ডেটাসেটের জন্য হাতে-কলমে partitioning ডিজাইন এবং Oracle-এর অফিসিয়াল ডকুমেন্টেশনের ভিত্তিতে তৈরি।

সম্পর্কিত লেখা

💬