6 دقیقه مطالعه

کندی Postgres در Next.js اغلب شکل کوئری است، نه کمبود سرور

Mehdi Rezaei
Mehdi
نویسنده

کندی Postgres در Next.js اغلب شکل کوئری است، نه کمبود سرور

وقتی اپ Next.js پشت Postgres کند می‌شود، اولین درخواست معمولاً زیرساخت بیشتر است. دیتابیس بزرگ‌تر، رپلیکای خواندن، کش، صف. گاهی حق با همین‌هاست. بیشتر وقت‌ها اپ سؤالی می‌پرسد که با صفحه محصول یکی نیست.

شکل کوئری همان مسئله کسل‌کننده است که زود برمی‌گردد. صفحه ده مطلب منتشرشده می‌خواهد با عنوان، اسلاگ، تاریخ، دسته، و توضیح کوتاه. API بدنه کامل CMS، هر رابطه، رکورد نویسنده، و فراداده تصویر را برمی‌گرداند. داشبورد تعداد به تفکیک وضعیت می‌خواهد. کد همه ردیف‌ها را می‌آورد و در جاوااسکریپت می‌شمارد. جستجو صفحه‌بندی مکان‌نما می‌خواهد. کوئری `OFFSET` را روی جدول روبه‌رشد می‌زند.

از صفحه شروع کن، نه از شعار کندی Postgres

سؤال مفید این نیست که «Postgres کند است؟». این است که این صفحه برای رندر به چه فیلدی نیاز دارد. فهرست را بنویس. بعد با کوئری مقایسه کن. در Payload CMS و خیلی اپ‌های ORM، پر کردن پیش‌فرض رابطه‌ها بی‌سروصدا بیشتر از نیاز صفحه می‌آورد. برای توسعه راحت است و زیر ترافیک گران.

فیلد کمتر انتخاب کن. رابطه را محدود کن. صفحه‌بندی را در دیتابیس انجام بده. فیلتر را به SQL ببر. مرتب‌سازی روی ستون ایندکس‌شده باشد. بدنه کامل مقاله را برای کارتی که عنوان و خلاصه نشان می‌دهد نیاور. سریع‌ترین بایت همان است که از Postgres نخواستی.

برای فهرست مقاله، فرق بین یک کوئری باریک و کشیدن گراف شیء CMS در هر درخواست است. سایت عمومی که فهرستش هفته‌ای یک‌بار عوض می‌شود نباید بهای سند کامل را برای هر بازدید بدهد.

شمارش را هم به دیتابیس بسپار. `COUNT` با فیلتر درست، از بار کردن ردیف و `.length` هم ارزان‌تر است هم کمتر دروغ می‌گوید، به شرطی که همان فیلتری باشد که روی صفحه است نه تقریبی فراموش‌شده.

ایندکس باید با فیلتر واقعی یکی باشد

ایندکس تزئین نیست. باید با فیلتر و ترتیبی که اپ واقعاً می‌زند بخواند. کوئری وبلاگ اغلب وضعیت انتشار را فیلتر می‌کند، با تاریخ مرتب می‌کند، و به دسته وصل می‌شود. داشبورد شاید با شناسه سازمان و وضعیت فیلتر کند. جستجو شاید مستأجر، تاریخ ساخت، و حذف نرم را با هم داشته باشد.

پنج ایندکس حدسی چون یک ابزار پیشنهاد داده اضافه نکن. `EXPLAIN` را بخوان، کوئری کند را ببین، و کوچک‌ترین ایندکسی را بگذار که همان مسیر دسترسی را پوشش دهد. ایندکس ترکیبی وقتی ترتیب ستون با کوئری می‌خواند قوی است. وقتی هیچ‌کس دلیلش را نمی‌داند نویز است و نوشتن را هم کند می‌کند.

بعد از ساخت ایندکس، مطمئن شو نقشه اجرا عوض شده و خود endpoint بهتر شده. اگر هنوز محموله غول است یا مسیر منتظر API بیرونی است، ایندکس تمام مسئله نبوده. گراف کوئری را دوباره با فیلدهای روی صفحه مقایسه کن.

`OFFSET` عمیق را ایندکس نجات نمی‌دهد به شکلی که بازاریابی می‌گوید. برای فهرست بلند، صفحه‌بندی بر اساس مکان‌نما روی ستون مرتبِ پایدار معمولاً شکل درست‌تری است. این را وقتی لازم داری که صفحه بعدی واقعاً وجود دارد، نه برای پنج ردیف.

کش بدون داستان باطل‌سازی، باگ تازه‌است

Next.js چند مرز کش می‌دهد و همین هم مفید است هم خطرناک. تولید ایستا، کش `fetch`، بازتولید با برچسب، Route Handler، و رفتار CDN همه می‌توانند به اپ پشت Postgres کمک کنند. اگر کسی مالک باطل‌سازی نباشد، محتوا غلط می‌ماند.

برای محتوای CMS، مسیر خواندن عمومی را کش کن و وقتی سند عوض شد بازتولید کن. برای داشبورد واردشده، داده مرجع پایدار را می‌شود کش کرد ولی داده حساس به مجوز باید تازه بماند. برای خلاصه گران، کلید کش را به نسخه ورودی ببند تا ویرایش، نتیجه کهنه را نشان ندهد.

اشتباه این است که قبل از جواب به «بعد از نوشتن چه باید دیده شود» Redis اضافه کنی. اگر مشتری پروژه را به‌روز کرد و داشبورد هنوز وضعیت دیروز را نشان داد، کش بخشی از باگ است. یک کوئری ساده با ایندکس درست اغلب بهتر از کش هوشمندانه‌ای است که هیچ‌کس به آن اعتماد ندارد.

مرز کش را با مرز صفحه یکی کن. صفحه بازاریابی و صفحه وضعیت حساب نباید سیاست یکسان داشته باشند فقط چون هر دو `fetch` دارند. `no-store` روی همه‌چیز یعنی یکی از دلیل‌های استفاده از فریمورک را خط زده‌ای. دینامیک شدن تصادفی به‌خاطر خواندن کوکی در layout ریشه هم همان مالیات را از مسیر دیگر می‌گیرد.

تعداد اتصال جزو طراحی اپ است

استقرار serverless اگر اتصال را شلخته باز کند، Postgres را تنبیه می‌کند. هر نمونه تابع ممکن است اتصال بسازد. جهش ترافیک به سقف استخر می‌خورد. کوئری طولانی اتصال را نگه می‌دارد در حالی که کاربر منتظر است. pooler مدیریت‌شده کمک می‌کند، ولی مسیری را که در هر درخواست کار زیاد می‌کند درمان نمی‌کند.

کار دیتابیس را کوتاه نگه دار. خواندن‌هایی را که صفحه با هم لازم دارد دسته‌ای کن. N+1 رابطه را نپذیر. خروجی سنگین، گزارش، و پردازش طولانی را ببر به کار پس‌زمینه. مهلت بگذار تا کوئری بد بلند و واضح بشکند، نه اینکه استخر را تا افت سایت نگه دارد.

این موضوع فقط نکته عملکرد نیست. سایت کند Next.js پشت Postgres معمولاً مالک داده نامشخص، کوئری چاق، ایندکس ناقص، مرز کش ضعیف، و نبود سنجش پروداکشن را با هم دارد. اصلاح کوئری در ورود است. ارزش اصلی در مرتب کردن اطراف آن است.

ممیزی کوتاه

سه صفحه کندی را که به درآمد یا اعتماد مربوط‌اند انتخاب کن. کوئری‌هایشان را بردار. فیلد انتخاب‌شده را با فیلد رندرشده مقایسه کن. نقشه کند را اجرا کن. فقط جایی ایندکس اضافه کن که نقشه اثبات کند لازم است. کش را فقط جایی بگذار که می‌توانی بگویی کدام نوشتن آن را باطل می‌کند. اتصال را در یک مسیر پرترافیک بشمار، نه با حدس.

اگر بعد از این هنوز CPU دیتابیس اشباع است، آن وقت حرف رپلیکا و اندازه بزرگ‌تر معنی دارد. قبل از آن، پول زیرساخت اغلب هزینه شکل غلط سؤال را قایم می‌کند.

پرسش‌های کوتاه

همیشه باید ORM را کنار بگذارم تا سریع شود؟ نه. ORM اگر انتخاب فیلد و رابطه را صریح کند کافی است. کندی از پنهان شدن بار اضافه می‌آید، نه از وجود تایپ.

Redis را کی بیاورم؟ وقتی سؤال دیتابیس باریک است، ایندکس با فیلتر می‌خواند، و هنوز یک نتیجه پایدار را بیش از حد حساب می‌کنی و داستان باطل‌سازی را نوشته‌ای.

فیلد اضافه در API داخلی اشکال دارد؟ برای یک ابزار داخلی کم‌ترافیک شاید نه. برای صفحه عمومی زیر بار، همان فیلد اضافه تبدیل به عادت گراف چاق می‌شود.

Share this article

کندی Postgres در Next.js اغلب شکل کوئری است، نه کمبود سرور | Mehd.ir