مدیریت درخواستها از پایگاه داده یکی از گلوگاههای مهم در برنامهنویسی است. رعایت نکردن برخی نکتهها در هنگام ارتباط با پایگاه داده میتواند اثرهایی جدی بر عملکرد نرمافزار داشته باشد.
یکی از فراگیرترین مشکلهایی که در برنامهنویسی پایگاه داده با آن روبرو هستیم، مشکل N+1 است. برای آشنا شدن با این مشکل از یک مثال استفاده میکنیم.
فرض کنید در یک فروشگاه مجازی، کاربر نامی تجاری را جستجو میکند و قصد دارد تمام محصولات آن نام تجاری و فروشگاههای ارائه دهندهی آنها را در فهرستی مشاهده کند.
نخستین روشی که به ذهن میرسد، جستجوی کالاهای تولیدشده توسط نام تجاری و سپس جستجوی تک به تک فروشگاههای ارائه دهندهی آن کالا است.
در این روش، یک کوئری برای کالاها و N کوئری برای یافتن فروشگاههای ارائهدهندهی هر کالا اجرا خواهد شد.( روش N+1 )
-- Query 1 SELECT G.id FROM Goods AS G WHERE G.brand = 'ACME'; -- Query 1 + 1 SELECT P.name FROM Providers AS P WHERE P.goods_id = id1; -- Query 1 + 2 SELECT P.name FROM Providers AS P WHERE P.goods_id = id2 -- ... -- Query 1 + N SELECT P.name FROM Providers AS P WHERE P.goods_id = idN |
اجرای هر کوئری علاوه بر بار پردازشی که روی پایگاه داده ایجاد میکند، مستلزم ارسال و دریافت اطلاعات، بررسی دسترسیها، احتمالا ایجاد جدولهای موقتی در حافظه و ... است. نادرستی این روش آشکار است.
برای حل مشکل N+1 شیوههای گوناگونی پیشنهاد شده است. به طور ویژه در برخی از ORMها راهحلهایی وجود دارد که باید مورد مطالعه و استفاده قرار گیرد.
در ادامه دو روش دستی که میتواند این مشکل را برطرف کند مشاهده خواهید کرد:
-- Query 1 SELECT G.id FROM Goods AS G WHERE G.brand = 'ACME'; -- Query 2 SELECT P.name FROM Providers AS P WHERE P.goods_id IN ( id1, id2, ... ) ORDER BY P.goods_id |
و روش دوم که استفاده از آن نیازمند توجه به نکتههای خاص است
-- Query 1 SELECT G.id, P.name FROM Goods AS G LEFT JOIN Providers AS P ON G.id = P.goods_id WHERE G.brand = 'ACME' ORDER BY G.id; |
برای استفاده از این شیوه، چند نکته قابل توجه است
- مرتبکردن نتایج بر اساس شناسهی کالا برای استفادهی بهینه از نتایج الزامی است
- در این روش، به ازای هر فروشنده، اطلاعات کالا تکرار میشوند. بنابراین کاهش تعداد فیلدهای بازگشتی از پایگاه داده میتواند در کاهش بار شبکه و کاهش بار روی پایگاه داده اثر زیادی بگذارد.
- ممکن است برخی از پایگاههای داده در هنگام JOIN جدولها نتوانند از indexها استفاده کنند و مجبور شوند از جدولهای موقتی استفاده کنند. این موضوع عملکرد را به شدت کاهش میدهد.
- شیوهی کدنویسی در این کوئری با شیوههای دیگر متفاوت است که دقت بیشتری را طلب میکند