شاید شما هم مطالب زیادی در مورد پایگاه داده ها و مزایا و معایب هر یک شنیده باشید. با وجود رشد روزافزون پایگاه داده های غیر رابطهای، هنوز هم استفاده از RDBMS ها، سهم عمده ای از نرم افزارهای توسعه یافته و یا در حال توسعه رو در اختیار داره. در این مقاله قصد دارم تا تجربیاتم از کار با پایگاه دادهها(به خصوص RDBMS ها) رو با شما عزیزان به اشتراک بگذارم. این تجربیات در عین اختصار، میتونه معجزه گر باشه و شما رو از گلوگاه های خطرناک در توسعه و پشتیبانی نرم افزار نجات بده. پس با دقت و تفکر ویژه ای به مطالعه بپردازید.
1) از پایگاه داده ها انتظار معجزه نداشته باشید.
با وجود قدرت بسیار زیاد پایگاه داده ها و پیشرفت های چشم گیری که در سالهای اخیر داشته اند، هنوز باید در استفاده و طراحی دیتابیس، نهایت دقت و ریزبینی را به کار بگیرید. پایگاه داده، در نهایت قدرت، معجزه نخواهد کرد بنابراین با تکیه به قدرت پایگاه داده، جانب احتیاط را کنار نگذارید.
2) تمام انواع پایگاه داده کاربردی هستند، از تعصب دوری کنید.
شاید در طول سالهای کاری خود، با نگاه های متعصبانه ای نسبت به پایگاه داده ها روبرو شوید. هر پایگاه داده در صورت استفاده در جایگاه مناسب خود، میتواند بهترین کارایی را داشته باشد.
3) پرفورمنس در زمان تست را با زمان استفاده عملیاتی اشتباه نگیرید.
در موارد بسیاری، افراد با توجه به اینکه در زمان تست حجم داده های کمی در دیتابیس قرار دارد، متوجه ناکارآمد بودن کوئری ها و طراحی ها نخواهند شد و در زمان استفاده عملیات و انتشار عمومی محصول، با مشکلات زیادی مواجه میشوند. در هر زمان باید تمام تلاش خود را برای رسیدن به بهترین پرفورمنس به کار گیرید.
4) از هارد SSD استفاده کنید.
با توجه به اینکه ماهیت پایگاه داده، ذخیره داده روی حافظه های دائمی است، استفاده از هاردهای پرسرعت تاثیر معجزه آسایی در افزایش سرعت پایگاه داده در کلیه عملیات دارد.
5) در خواندن داده ها از پایگاه داده، برای واکشی لیست داده ها از Lazy Load استفاده کنید.
6) کوئری های بهینه(optimized) بنویسید.
کوئری های طراحی شده توسط شما، باید دقیقا خواسته مسئله را ارائه کنند نه فراتر از آن. معمولا در تب و تاب رسیدن به خواسته مسئله، رعایت بهینه بودن کوئری به فراموشی سپرده میشود.
گاهی برای رسیدن به یک پاسخ، چندین کوئری و روش مختلف قابل استفاده است. سعی کنید تا کم هزینه ترین کوئری را انتخاب کنید.
مثال:
· مثال: عدم محدود کردن تعداد داده های خروجی برای یافتن یک رکورد خاص.
Wrong: Select * from User where UserName ='...' Correct: Select top(1) * from User where UserName='...'
در این مثال، با توجه به Unique بودن Username، خروجی دو کوئری مشابه خواهد بود، اما کوئری غلط نسبت به کوئری صحیح هزینه چندین برابری خواهد داشت.
· مثال: محدود نکردن داده ها در کوئری های پیچیده تر
Wrong: select * from Products inner join Categories on Products.CategoryId=Categories.Id order by Products.Id OFFSET 10 rows FETCH NEXT 10 ROWS ONLY Correct: select * from ( select * from Products order by Products.Id OFFSET 10 rows fetch next 10 rows ONLY) TempProducts inner join Categories on TempProducts.CategoryId=Categories.Id
در کوئری های فوق قصد داریم اطلاعات تعدادی از کالا ها را به صورت Lazy Load(ده رکورد بعد از دهمین رکورد) در کنار اطلاعات دسته بندی آنها قرار دهیم. دو روش غلط و صحیح ارائه شده خروجی مشابهی خواهند داشت، اما مورد صحیح به مراتب هزینه کمتری ایجاد خواهد کرد.
· مثال: گاهی برای کار با پایگاه داده از ORM ها استفاده میکنیم. بسیاری از افراد به جای استخراج دادههای هدف از پایگاه داده، تعداد بسیار زیادی از رکوردها را به حافظه Ram واکشی میکنند و سپس، از این حجم داده ها تعداد بسیار کمی که هدف اصلی عملیات است را انتخاب میکنند. با توجه به اینکه ORM ها جهت سهولت کدنویسی، شما را با بسیاری از ملاحظات درگیر نمیکنند و در مراحل تست اولیه، بار سنگین این نوع خروجی ها احساس نمیشود، معمولا چنین اشتباهاتی رخ میدهد.
اشتباهات رایج بیشماری وجود دارد که با کمی تفکر و دقت میتوان به کوئری دقیق و صحیح دست یافت.
7) مفهوم Lock دیتا در پایگاه داده را نادیده نگیرید.
زمانی که یک کوئری اجرا میشود، به طور معمول تا مشخص نشدن نتیجه آن، داده های مرتبط با خروجی کوئری لاک(Lock) میشوند. در این زمان، سایر کوئری های مرتبط با لاک، در انتظار اتمام آن باقی میمانند و سپس اجرا شده و خود باعث لاک جدیدی میشوند. اگر چه در صورت طراحی صحیح پایگاه داده و کوئری ها، زمان لاک بسیار کم خواهد بود؛ اما در صورت زیاد شدن درخواست ها به پایگاه داده و بروز موارد، ممکن است پایگاه داده در نتیجه بسیاری از درخواست ها با کندی بسیار زیاد، Block ها و Deadlock ها مواجه شود. این اتفاق زمانی که تعداد رکوردها در تعدادی از جداول بسیار زیاد است و روابط زیادی برای پایگاه داده در نظر گرفته شده است بیشتر به وقوع میپیوندد.(به زبان ساده در جدولی که تنها 10 رکورد دارد، معمولا Lock چشم گیری نداریم؛ اما در جدولی که تعداد داده ها به چند میلیون میرسید خطر بیشتری وجود دارد.)
بنابراین به دلایل ذکر شده، حتی المقدور در کوئری هایی که مطمئنا نیازی به لاک شدن داده ها ندارند، از no lock استفاده کنیم تا از لاک بیهوده جلوگیری شود.
8) در استفاده از Transaction احتیاط کنید.
با توجه به اینکه Transaction ها از خاصیت ACID برخوردارند، در زمان اجرای یک Transaction جداول مرتبط با آن Lock میشود. با توجه به ذات Transaction ها و منطق استفاده از آنها، ممکن است تعداد زیادی از جداول را با خود درگیر و در واقع Lock کند. در صورت زیاد شدن تعداد لاک ها و زمانبر بودن فرآیند یک Transaction، بروز Block و Deadlock ها و کندی بسیار زیاد دور از انتظار نیست.
9) روابط را منطقا حفظ کنید.
بسیاری از پایگاه داده های رابطه ای این امکان را به شما میدهند تا روابط میان جداول را به آنها معرفی کنید و سپس در زمان اینزرت، اپدیت یا حذف داده ها، به صورت خودکار بر اساس این روابط Checking هایی برای جلوگیری از تناقض، به عملیات اضافه میکنند. در صورت بالا بودن حجم داده ها، این چکینگ ها میتواند پرفورمنس را با کاهش چشم گیر و خطرناکی مواجه کند. بنابراین بهتر است در فرآیندهای نرم افزار خود روابط را به دقت در نظر بگیرید(تا منطقا تناقضی اتفاق نیفتد) و پایگاه داده را از این بررسی های پر هزینه رها سازید.
10) در استفاده از کوئری های پرهزینه احتیاط کنید.
کوئری هایی همچون Union، Intersect، Except، Join، GroupBy، Distinct، In، Not Inمعمولا هزینه زیادی در اجرا خواهند داشت. از استفاده بی رویه این کوئری ها خودداری کنید.
11) در ایندکس گذاری تعادل را رعایت کنید.
ایندکس گذاری موجب ایجاد الگوریتم هایی در پس زمینه عملیات پایگاه داده میشوند که معمولا در خواندن و واکشی اطلاعات باعث افزایش چشم گیر سرعت خواهند بود و در عین حال به دلیل اجرای همین الگوریتم ها، در زمان ایجاد یا ویرایش داده ها باعث کندی محسوسی میشوند.
معمولا در ایندکس گذاری اشتباهات زیر رخ میدهد.
· عدم استفاده از ایندکس: معمولا جداول بر حسب استفاده و حجم داده های خود، نیازمند ایندکس گذاری مناسب هستند. عدم استفاده از ایندکس ها موجب کندی در خواندن اطلاعات میشود.
· عدم ایندکس گذاری دقیق: گاها عدم شناخت صحیح نسبت به کوئری ها موجب ایندکس گذاری هایی میشود که صرفا کندی زیاد در زمان آپدیت یا اینزرت را به همراه دارند و در عین حال تاثیری در سرعت واکشی اطلاعات ندارند.
· ایندکس گذاری بیش از حد: گاها استفاده بی رویه در ایندکس گذاری، کندی بسیار زیادی در عملیات اینزرت و آپدیت به همراه دارد، اگر چه ممکن است سرعت واکشی اطلاعات را بسیار بالا ببرد.
در مجموع با توجه به موارد گفته شده، بر حسب استفاده و اهمیت جداول، ایندکس گذاری صحیح و دقیقی انجام دهید.
12) تنظیمات FileGroup را انجام دهید.
وقتی که یک دیتابیس ایجاد میکنید، دو فایل جهت نگهداری داده های پایگاه داده با پسوندهای MDF و LDF ایجاد میشود که به ترتیب داده ها و اطلاعات لاگ در این دو فایل ذخیره میشود. شما میتوانید با استفاده از FileGroup ها پایگاه داده را به گونه ای پیکربندی کنید که داده ها در چند فایل در مکان های مختلفی از HardDisk ذخیره شود. به طور مثال میتوانید مشخص کنید که داده های هر جدول در کدام FileGroup قرار گیرد. این عملیات میتواند تاثیر بسیار زیادی در Performance داشته باشد.
13) به ORM ها به هیچ وجه اعتماد نکنید(بسیار مهم).
در تمامی سیستم های نرم افزاری، نقاطی وجود دارد که حساسیت بسیار بالایی در اجرای صحیح کوئری ها وجود دارد. به طور مثال عملیات رزرو و کنترل تعداد محصولات در انبار را در نظر بگیرید. در صورت عدم کنترل دقیق تعداد و موجودی کالاها، امکان برور فاجعه وجود خواهد داشت. در مواردی که دارای حساسیت های این چنینی هستند، به جای ORM، از Procedure ها استفاده کنید.
شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.
برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.