بایگانی

نوشته‌هایی که ‘Lazy Loading’ برچسب زده شده‌اند

مشکلات پیش رو پس از راه‌اندازی Lazy Loading در NHibernate

در نسخه جدید NHibernate رفتار پیش‌فرض برای بارگذاری داده‌ها استفاده از روش Lazy Loading است و تا زمانی که به سطحی از داده‌ها نیاز نداشته باشیم، آن سطح از داده‌ها در حافظه بارگذاری نخواهد شد.

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

۱- بارگذاری نشدن داده‌های مرتبط با آبجکت مورد نظر ما:

به عنوان مثال در نمونه روبرو اگر داده‌های مربوط به کلاس Order را در حافظه بارگذاری نماییم یا به طور دقیق‌تر اگر توسط متد Get یک سفارش (order) را از پایگاه داده خوانده و در حافظه قرار دهیم و session را ببندیم، در این صورت در هنگام فراخوانی یکی از مشخصه‌های مرتبط با کلاس‌های مرتبط با این کلاس با خطا مواجه خواهیم شد. مثلا برای اجرای این خط از کد

string name = Order.Customer.CompanyName;

با خطا مواجه خواهیم شد. دلیل این است که در Lazy Loading و در اجرای متد Get کوئری ساخته شده دارای هیچ join ای با هیچ کدام از جداول معادل کلاس‌های دیگر نیست و عملا ما به داده‌های کلاس‌های دیگر دسترسی نداشته‌ایم.

۲- مشکل n + 1 عبارت select :

اگر پس از بارگذاری یک Order بخواهیم به آیتم‌های OrderLine دسترسی پیدا کنیم، در این صورت به ازای هر آیتمی که به آن دسترسی پیدا می‌کنیم یک عبارت select ساخته می‌شود. بنابراین اگر دارای n آیتم باشیم  و بخواهیم به تمام آن‌ها دسترسی پیدا کنیم، یک عبارت select برای خود order و n عبارت برای تمام آیتم‌های مرتبط با آن ساخته می‌شود که در نتیجه دارای n+1 عبارت select خواهیم بود (دلیل نامگذاری). این امر می‌تواند عملیات واکشی داده‌ها را کند نماید و سبب سرباری روی وایگاه داده می‌شود.

فرض کنید دارای یک collection هستید که دارای چند صد آیتم باشد و ما فقط نیاز به دسترسی به یک یا دو مورد از آن‌ها هستیم. اگر بخواهیم تمام آیتم‌ها را بارگذاری کنیم مقادیر زیادی از منابع خود را از دست خواهیم داد اما خوشبختانه NHibernate دارای راه حلی برای این مورد است، این راه حل Eager Loading نام دارد.


مقایسه عملکرد NHibernate با استفاده از Lazy Loading و بدون آن

برای مقایسه نسخه‌های 1.2.0 و 2.1.2 چند عمل انجام شد. برای این کار یک پروژه جدید ساخته شد و داده‌هایی به صورت تصادفی وارد آن شد. این عمل با تعداد رکوردهای مختلف برای هر جدول از پایگاه داده انجام شد تا بتوان نموداری برای نتیجه‌گیری رسم کرد.
شکل زیر مدل آبجکتی برنامه مورد نظر را نشان می‌دهد :

در این مدل قابلیت‌های پایه‌ای یک سیستم سفارش محصول پیاده‌سازی شده است، بدین ترتیب که در این سیستم مشتری‌ها به همراه برخی از اطلاعات مربوط به آنها و همچنین محصولات قابل ارائه برای فروش تعریف می‌شوند. جدول سفارشات (order) هم رابطه بین مشتری‌ها و محصولات انتخابی را نگهداری می‌کند یعنی عملا سفارشات مشتری‌ها با استفاده از این ارتباطات ذخیره می‌شوند.
در مرتبه اول این جداول را با ۵۰۰۰ مشتری و ۵۰۰۰ محصول  و ۵۰۰۰ سفارش که هر کدام دارای مشتری‌ها و محصولات تصادفی است پر گردید و عملیات load داده‌ها در دو وضعیت فعال و غیرفعال lazy loading انجام شد. برای هر کدام از این  اعمال، مدت زمان انجام کار بر مبنای میلی‌ثانیه ثبت گردید.
در دفعات بعد این اعمال با تعداد دفعات ۱۰۰۰۰ تا ۵۰۰۰۰ و با نرخ رشد ۱۰۰۰۰ انجام شد و زمان‌های مورد نظر اندازه‌گیری شد.

جدول زیر از انجام کارهای بالا شکل گرفت:

تعداد lazy = false lazy = true
5000 51234.375 500
10000 286368.69 718.75
20000 330031.25 1328.125
30000 430937.5 1875
40000 533718.75 2593.75
50000 885328.125 3124.98

نمودار زیر برای مقایسه بهتر اعداد بالا و دیدن تفوت بسیار چشمگیر این دو روش با هم رسم شده است.

نمودار مقایسه NHibernate با استفاده از Lazy و بدون آن

همان‌طور که می‌بینید تفاوت بسیار چشمگیر است و با به روزرسانی روش‌های استفاده شده می‌توان به کارایی بسیار بهتری دست یافت.

دنبال‌کردن

هر نوشتهٔ تازه‌ای را در نامه‌دان خود دریافت نمایید.