تلهی JOIN در Firestore
شما با یک مشکل رایج در Firestore روبرو هستید. تابع Firebase شما خطای حداکثر اندازه دسته (batch size) میدهد. برای یک داشبورد، نیاز دارید سفارشها (orders) و مشتریان (customers) را با هم JOIN کنید. معمولاً برای رفع این مشکل، دادهها را کپی (duplicate) میکنید. اما حالا دادههای شما قدیمی و ناسازگار شدهاند.
گوگل برای حل این مشکل، Pipelines API را معرفی کرد. این API اجازه میدهد بدون کپی کردن دادهها، عملیات JOIN را بین مجموعهها (collections) انجام دهید. برخی از توسعهدهندگان در تستهای کوچک، زمانهای پرسوجوی (query) سریعی را گزارش کردهاند.
من یک هفته را صرف تست این API تحت بار سنگین کردم. در اینجا چیزهایی آمده است که مستندات به شما نمیگویند.
۱. هزینههای بالا
هر اجرای pipeline از تمام مجموعههای درگیر، داده میخواند. یک JOIN بین دو مجموعه، هزینه خواندن (reads) هر دو را از شما دریافت میکند. اگر دو مجموعه با ۵۰,۰۰۰ سند را با هم JOIN کنید، هزینههای شما به شکلی نامناسب افزایش مییابد. این یک هزینه خطی ساده نیست.
۲. محدودیتهای عملکردی
در تستهای من، یک pipeline روی ۱۰,۰۰۰ سند، ۳۸۰ میلیثانیه زمان برد. وقتی ۱۰۰,۰۰۰ سند را تست کردم، پرسوجو در ۳۰ ثانیه با خطا (timeout) مواجه شد. شما مشکل را حل نمیکنید، بلکه فقط یک خطای batch را به یک خطای timeout تبدیل میکنید.
۳. مشکلات شروع سرد (Cold Start)
قابلیت Pipelines یک محیط اجرای مجزا ایجاد میکند. در محیطهای بدون سرور (serverless) مانند Cloud Functions، این کار ۲ تا ۴ ثانیه تأخیر اضافه میکند. کاربران شما فکر خواهند کرد اپلیکیشن شما کند است.
Pipelines API ابزاری برای نمونهسازی (prototyping) یا مجموعههای کوچک زیر ۵,۰۰۰ سند است. این جایگزینی برای یک پایگاه داده رابطهای (relational database) نیست. گوگل این قابلیت را ارائه میدهد تا به شما کمک کند به جای مهاجرت به PostgreSQL یا Spanner، در اکوسیستم Firebase باقی بمانید.
اگر از Pipelines استفاده میکنید، این قوانین را رعایت کنید:
• اندازه مجموعه خود را بررسی کنید. اگر یک مجموعه از ۲۰,۰۰۰ سند فراتر رفت، ابتدا هزینه JOIN را محاسبه کنید. • پیچیدگی را محدود کنید. انجام JOIN بین سه مجموعه یا بیشتر، نشانه بدی است. • هزینههای خواندن را بهصورت هفتگی پیگیری کنید. خواندنهای Pipeline در صورتحساب شما به شکل متفاوتی ظاهر میشوند. • دادههای غیرنرمالسازیشده (denormalized) خود را حفظ کنید. از Pipelines به عنوان یک مکمل استفاده کنید، نه یک جایگزین کامل. • با ترافیک واقعی تست کنید. بنچمارکها روی مجموعههای خلوت، واقعیت محیط عملیاتی (production) را منعکس نمیکنند.
از یک چسب زخم برای اجتناب از یک تصمیم معماری واقعی استفاده نکنید.
شما روابط را در Firestore چگونه مدیریت میکنید؟ آیا از denormalization استفاده میکنید یا client-side joins؟ در کامنتها به من بگویید.
