سفارش، موجودی و پرداخت را در ماژولهای روشن قرار دادهایم. حالا نوبت دیتابیس است و پیشنهادها سریع از راه میرسند: رابطهای برای تراکنش، سندی برای انعطاف، موتور جستوجو برای متن و یک انبار داده برای گزارش. اما پیش از اضافهکردن چند محل نگهداری، باید بدانیم برنامه دقیقاً چه چیزی را چگونه میخواند و تغییر میدهد.
در بخش قبل، مالکیت داده را از مرز استقرار جدا کردیم. این بخش همان API سفارش را از زاویه الگوی دسترسی بررسی میکند. آشنایی با جدول و درخواست API کافی است. خروجی، فهرست عملیات و یک تصمیم اولیه مستند است؛ انتخاب محصول دیتابیس را بر پایه نیاز میسنجیم، نه محبوبیت نام آن.
از نام موجودیت به فهرست عملیات برسیم
اینکه موجودیتهایی به نام سفارش و کالا داریم، برای انتخاب کافی نیست. باید بدانیم سفارش با شناسه پیدا میشود یا با چند فیلتر، چند بار وضعیتش تغییر میکند و گزارش کدام بازه را میخواند. تفاوت این عملیات روی مدل داده، ایندکس و هزینه اجرا اثر مستقیم دارد.
برای مسیر اصلی، خواندن و نوشتن را جدا ثبت کنیم. ثبت سفارش ممکن است نیاز به اعتبارسنجی اقلام و تخصیص موجودی داشته باشد؛ صفحه عملیات ممکن است سفارشهای یک وضعیت را با مرتبسازی زمانی بخواهد. این دو را در یک عبارت کلی مثل «CRUD سفارش» پنهان نکنیم.
| عملیات | دسترسی اصلی | نیاز مهم |
|---|---|---|
| ثبت سفارش | نوشتن سفارش و اقلام و تخصیص | سازگاری تغییرهای وابسته |
| جزئیات سفارش | خواندن با شناسه و مجوز | نتیجه معتبر و محدود به کاربر |
| صف آمادهسازی | فیلتر وضعیت و مرتبسازی | صفحهبندی و ایندکس مناسب |
| جستوجوی توضیح | تطبیق متن و احتمالاً رتبهبندی | تعریف معنای جستوجو |
| گزارش فروش | تجمیع یک بازه داده | تازگی قابل قبول و فشار کنترلشده |
تراکنش را با نیاز به همهیاهیچ تعریف کنیم
اگر سفارش ثبت شود ولی تخصیص موجودی شکست بخورد، چه وضعیتی معتبر است؟ شاید محصول اجازه سفارش معلق بدهد؛ شاید لازم باشد تغییرهای مرتبط با هم موفق یا لغو شوند. پاسخ به این پرسش، نیاز تراکنش را روشن میکند. نباید صرفاً چون چند دستور داریم، بدون فهم قاعده درباره مرز تراکنش تصمیم بگیریم.
دیتابیسهای رابطهای مانند PostgreSQL و MySQL با موتور InnoDB امکانات تراکنش دارند. بااینحال تراکنش بهتنهایی همه رقابتهای همزمان را حل نمیکند؛ سطح جداسازی، قفل و شرط بهروزرسانی هم اهمیت دارند. همچنین نمیتوان گفت هر دیتابیس غیررابطهای فاقد تراکنش است؛ قابلیت و محدوده تضمین هر محصول باید جداگانه بررسی شود.
رابطهها را بر اساس مسیر تغییر مدل کنیم
یک سفارش چند قلم دارد و هر قلم به کالا اشاره میکند. مدل رابطهای میتواند این رابطهها و قیود را روشن نگه دارد. اما باید مشخص باشد کدام اطلاعات در زمان خرید تثبیت میشوند. مثلاً تغییر نام یا قیمت فعلی کالا نباید لزوماً سابقه سفارش قبلی را بازنویسی کند.
این مسئله فقط انتخاب SQL یا سند نیست؛ تصمیم دامنه است. شاید لازم باشد بخشی از مشخصات قلم بهعنوان تصویر زمان خرید در سفارش ثبت شود. اگر همین معنا روشن نباشد، هر فناوری انتخاب کنیم ممکن است گزارش تاریخی نادرست بسازیم.
انعطاف ساختار، حذف قرارداد نیست
گاهی اطلاعات بعضی کالاها متنوع است و ذخیره بخشی از ویژگیها بهصورت سند یا JSON قابل بررسی میشود. اما همچنان باید نوع، اعتبار و کاربرد داده معلوم باشد. اگر روی یک ویژگی فیلتر یا قاعده مالی اجرا میکنیم، نمیتوان آن را فقط یک مقدار آزاد بیقرارداد دانست.
پیش از انتخاب ساختار منعطف، بنویسید کدام بخش صرفاً نمایش داده میشود و کدام بخش در جستوجو، مرتبسازی یا تصمیم استفاده میشود. هزینه اعتبارسنجی و مهاجرت از بین نمیرود؛ ممکن است فقط از دیتابیس به برنامه منتقل شود.
جستوجوی دقیق با جستوجوی متنی یک نیاز نیست
پیداکردن سفارش با شناسه پیگیری با یافتن متن مشابه در توضیحات فرق دارد. در حالت اول، تطبیق دقیق و ایندکس معمولی ممکن است کافی باشد. در حالت دوم، شکستن واژه، رتبهبندی، غلط تایپی یا شکلهای مختلف حروف میتواند مطرح شود.
اول معنای جستوجو را با چند نمونه بنویسید. آیا جستوجوی «کفش» باید عبارت جمع یا غلط املایی را هم پیدا کند؟ در فارسی با ی و ک و نیمفاصله چه میکنیم؟ وجود قابلیت جستوجوی متن در یک دیتابیس به معنی پوشش خودکار تمام این انتظارها نیست؛ پیکربندی و نمونه واقعی باید آزمایش شوند.
ممکن است جستوجوی داخلی دیتابیس برای نیاز فعلی کافی باشد. افزودن موتور جدا، مسئولیت تازهکردن ایندکس و مدیریت فاصله آن با منبع اصلی را اضافه میکند. پیش از پذیرش این هزینه، محدودیت واقعی راهحل سادهتر را پیدا کنیم.
گزارش سنگین را با خواندن عادی اشتباه نگیریم
صفحه جزئیات معمولاً یک سفارش را میخواند؛ گزارش ممکن است ماهها داده را تجمیع کند. اگر هر دو بیبرنامه روی همان منبع اجرا شوند، گزارش میتواند با مسیر عملیاتی رقابت کند. اما این به معنی ضرورت فوری انبار داده نیست.
ابتدا حجم و دفعات گزارش و میزان تأخیر مجاز را بنویسید. شاید ساخت خروجی در پسزمینه یا اصلاح کوئری کافی باشد. اگر منبع خواندنی جدا استفاده شود، باید تأخیر همگامسازی و رفتار داده تازه روشن باشد؛ نتیجه گزارش ممکن است دقیقاً همزمان با تراکنش ثبت سفارش بهروز نباشد.
داده نماینده برای تصمیم لازم است
آزمون روی چند ردیف، هزینه واقعی فیلتر و مرتبسازی را نشان نمیدهد. اندازه جدول، توزیع وضعیتها و تعداد اقلام هر سفارش باید به فرضهای محصول نزدیک باشند. همچنین بعضی فیلترها انتخابپذیری بسیار متفاوتی دارند؛ جستوجوی یک شناسه با فهرست همه سفارشهای فعال یکی نیست.
در این مقاله بنچمارک اجرا نشده و عدد ظرفیت ارائه نمیکنیم. برنامه آزمایش باید نسخه دیتابیس، سختافزار، داده نمونه، کوئری و وضعیت کش را ثبت کند. در غیر این صورت، عدد زمان پاسخ بدون زمینه بهسختی قابل مقایسه است.
هزینه عملیات را کنار قابلیتها بگذاریم
تیم باید بتواند نسخه پشتیبان بگیرد، بازیابی کند، تغییر طرح داده را اجرا کند و مشکل کوئری را بفهمد. محصولی با قابلیت جذاب ولی تجربه عملیاتی نامعلوم میتواند برای تیم کوچک پرهزینه باشد. هزینه سرویس مدیریتشده و مسئولیت باقیمانده تیم هم باید روشن شود.
اگر دو گزینه نیازهای اصلی را پوشش میدهند، شناخت تیم و مسیر نگهداری معیار مهمی است. این به معنی ماندن همیشگی روی ابزار آشنا نیست؛ باید منفعت تغییر با هزینه آموزش و مهاجرت سنجیده شود، نه اینکه یکی از این دو نادیده گرفته شود.
تصمیم اولیه و شرط تغییر را ثبت کنیم
برای سامانه نمونه، میتوان یک دیتابیس رابطهای را نامزد اولیه نگهداری سفارش و موجودی قرار داد و جستوجو و گزارش را ابتدا با قابلیتهای همان محیط بررسی کرد. این تصمیم آموزشی است و باید با الگوی دسترسی و آزمایش واقعی پروژه تأیید شود.
کنار تصمیم بنویسید چه چیزی باعث بازبینی خواهد شد: نرسیدن کوئری مهم به هدف کیفیت پس از اصلاح، نیاز جستوجوی مشخصی که پوشش داده نمیشود یا فشار گزارش که مسیر عملیاتی را مختل میکند. با این روش، ابزار تازه پاسخی به شاهد خواهد بود، نه پیشفرض شروع کار.
تمرین و ادامه مسیر
پنج عملیات جدول را برای محصول خود تکمیل کنید و برای هرکدام، الگوی خواندن، نوشتن، تازگی و قاعده سازگاری را بنویسید. سپس یک سؤال انتخاب کنید که بدون آزمایش نمیتوان پاسخ داد. همین سؤال، هدف آزمایش بعدی خواهد شد.
در بخش چهارم سراغ ایندکس و EXPLAIN میرویم. بهجای افزودن حدسی ایندکس، کوئریهای همین فهرست را با داده نماینده بررسی میکنیم و دلیل هر تغییر را ثبت خواهیم کرد.
منابع رسمی
- تراکنشها در مستندات PostgreSQL.
- مدل تراکنش InnoDB در MySQL 8.4.
- جستوجوی متن در PostgreSQL؛ قابلیت و پیکربندی باید با زبان و داده پروژه بررسی شود.
