Data Modeling: সম্পর্ক, access pattern ও constraint
Relational Modeling and Access Patterns
এই পাঠের সূচিপত্র
এই পাঠে যা শিখবেন
- Access pattern থেকে entity ও relationship
- Primary/foreign key ও business constraint
- Laravel migration এবং historical order data
সমস্যা দিয়ে শুরু
একটি দোকানে order table-এ product_name, customer_name ও comma-separated product IDs রাখা হয়েছে। পরে জানতে হচ্ছে কোন customer কোন বই কতবার কিনেছেন। Search, integrity ও reporting কঠিন হয়ে গেছে। Schema design শুরুতে শুধু form-এর fields কপি করলে future query ও business history-এর boundary বোঝা যায় না।
সহজ করে বুঝি
Data modeling entity, identity, relationships এবং invariants প্রকাশ করে। Customer, order, order item ও product আলাদা concepts। One-to-many order items order-এর detail রাখে; many-to-many relationship-এর মাঝের row-তেও quantity ও purchase price-এর মতো meaning থাকতে পারে। Primary key identity দেয়, foreign key valid reference রাখে, unique constraint duplicate identity আটকায়। Access pattern বলে কোন filter, join ও sort গুরুত্বপূর্ণ। Schema-তে শুধু current product price রাখলে পুরোনো invoice-এর amount বদলে যেতে পারে।
পরিচিত একটি উপমা
বিক্রির receipt-এ সেই দিনের দাম লেখা থাকে; দোকানের আজকের price list দেখিয়ে গত বছরের receipt বদলানো যায় না। Customer register, product catalog ও receipt আলাদা খাতা হলেও reference number দিয়ে যুক্ত। Database relationships এই explicit reference-কে নিয়মিত করে।
নকশাটি দেখুন
Diagram লোড হচ্ছে…
Diagram-এর text flow দেখুন
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ ORDER_ITEM : contains
PRODUCT ||--o{ ORDER_ITEM : referencesএক customer অনেক order দিতে পারেন। Order-এ একাধিক item, item একটি product-এর reference রাখে। Product relation current catalog metadata দেয়, কিন্তু order item-এর unit_price_minor historical purchase snapshot। Database foreign key থাকা মানেই এক order-এ অন্তত একটি item আছে এমন সব invariant স্বয়ংক্রিয়ভাবে enforce হয় না; transaction ও application workflow দরকার।
PHP ও Laravel-এ প্রয়োগ
Migration up method-এর fragment; orders ও products table আগে আছে, একই connection ব্যবহার করে। PostgreSQL/MySQL supported schema ধরে integer minor units রাখা হয়েছে। Currency, tax ও refund model আলাদা যোগ করতে হবে। Product deletion policy restrict রাখা হয়েছে যেন history reference না ভাঙে।
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::create('order_items', function (Blueprint $table) {
$table->id();
$table->foreignId('order_id')->constrained()->cascadeOnDelete();
$table->foreignId('product_id')->constrained()->restrictOnDelete();
$table->unsignedInteger('quantity');
$table->unsignedBigInteger('unit_price_minor');
$table->char('currency', 3);
$table->timestamps();
$table->index(['order_id', 'product_id']);
});সুবিধা, সীমাবদ্ধতা ও trade-off
Normalized entities duplicate update কমায় এবং constraints সহজ করে। বেশি join read path ব্যয় বাড়াতে পারে; measured query থেকে targeted denormalization করুন। Product hard delete block হলে operations workflow দরকার, যেমন soft delete বা archived catalog। Cascade delete order history-এর retention policy অনুযায়ী ব্যবহার করুন; financial record নির্বিচারে cascade করা সব business-এর জন্য ঠিক নয়।
সাধারণ ভুল
- Money floating-point number-এ রেখে rounding drift তৈরি করা।
- সব relationship JSON/comma string-এ রেখে reference integrity বাদ দেওয়া।
- Current product price দিয়ে historical order total পুনর্গণনা করা।
আরও একটু গভীরে
Business key এবং surrogate ID ভিন্ন হতে পারে। External order number unique, কিন্তু internal primary key আলাদা রাখা যায়। Tenant scope থাকলে unique product SKU tenant_id-সহ হতে পারে। Constraint database-এ রাখলেও error client-friendly করে map করুন। Large table-এ new foreign key যোগ করার lock ও validation cost migration plan-এ ধরুন। Schema decision-এ expected data growth ও most frequent query লিখলে indexing discussion grounded থাকে।
মনে রাখুন
Entity identity, relationships ও invariant আগে লিখুন। Historical fact ও current catalog state আলাদা রাখুন। Access patterns schema-এর সঙ্গে indexing ও query plan-ও নির্দেশ করে।
নিজে চেষ্টা করুন
এক order-এ একই product দুইবার আলাদা discount-এ কেনা যাবে কি না ঠিক করুন। তারপর unique constraint দরকার কি না বিচার করুন। Customer delete request ও legal invoice retention-এর conflict-এর schema policy লিখুন।
নিজের বোঝা যাচাই করুন
1. Order item আলাদা কেন?
এক order-এর বহু line item আছে এবং প্রতিটির quantity/price নিজস্ব fact। Comma-separated IDs সেই relationship ও per-item fields ঠিকভাবে প্রকাশ করে না।
2. Foreign key সব invariant রাখে?
Reference valid রাখে, কিন্তু minimum item count বা total calculation-এর মতো rule আলাদা logic/constraint চাইতে পারে।
3. Purchase price snapshot কেন?
Product price পরে বদলালেও আগের financial fact স্থির থাকতে হবে। Current catalog relation দিয়ে history পুনর্লিখন ঠিক নয়।
4. Minor units সব currency-তে দুই decimal?
না। Currency exponent ভিন্ন হতে পারে। Integer representation-এর সঙ্গে currency metadata ও rounding rules স্পষ্ট রাখুন।
5. Cascade সবখানে ভালো?
না। Dependent data lifecycle অনুযায়ী বেছে নিন। Audit বা financial retention-এ restrict/archive policy দরকার হতে পারে।
আরও পড়ুন
এই পাঠের কুইজ
এই পাঠ থেকে ২টি প্রশ্ন। উত্তর দিয়ে ব্যাখ্যা দেখুন; অধ্যায়ের কুইজ আলাদাভাবে দিতে হবে।
এই পাঠের ২টি প্রশ্নের উত্তর দিন। পাস করতে দুটিই সঠিক হতে হবে।
জমা দেওয়ার পর সঠিক উত্তর ও ব্যাখ্যা দেখবেন। ফলাফল এই ব্রাউজারে সংরক্ষিত থাকবে। অনুশীলনের ফল অধ্যায় সম্পন্নের হিসাবে যোগ হয় না।
অগ্রগতি এই ব্রাউজারে সংরক্ষিত থাকে। শুধু পাঠ খুললে সম্পন্ন হয় না।