آموزش جنگو (Basic) : جلسه بیست و پنج | اندیس ها (index)

در این جلسه به بررسی اندیس گذاری در دیتابیس های جنگو خواهیم پرداخت . با ما همراه باشید .آموزش جنگو : جلسه بیست و پنج | اندیس ها (index)اندیس ها : اندیس های دیتابیساندیس (index) کردن در واقع راهی است برای بهینه سازی عملکرد یک دیتابیس با به حداقل رساندن تعداد دسترسی‌های مورد نیاز دیسک هنگام پردازش یک query است. هدف از اندیس‌‌‌ گذاری، فراهم کردن شرایطی است که با کمترین جستجو و به سادگی به یک داده‌‌‌ی مشخص دسترسی پیدا کنیم.کلاس Index در جنگو ,کار شما را برای ایجاد اندیس در دیتابیس راحت می کند . برای اضافه کردن Index به مدل خود باید کلاس Meta را برای آن ایجاد کنید و در لیستی با نام indexes تنظیمات خود را قرار دهید . به مثال زیر نگاه کنید .from django.db import models class Customer(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) class Meta: indexes =[ models.Index(fields=['last_name', 'first_name']), models.Index(fields=['first_name'], name='first_name_idx'), ]کلاس های Models.Index کلاس هایی هستند که برای ایجاد تنظیمات اندیس گذاری دیتابیس به کار می روند. اندیس گذاری نیز مبحثی در مورد دیتابیس ها است , پس در این مقاله توضیح داده نمی شود . کلاس Index چند option یا آرگومان دارد که هر یک کاری را انجام می دهند . ابتدا نگاهی کلی به نحوه استفاده از آن انداختیم. حال بیایید به آرگومان های آن نگاهی بیندازیم . (مقادیری که در داخل کلاس باید استفاده شوند مانند name در بالا و در دومین index)ایندکس ها : Index optionsمقدار پیش فرض استفاده از Index به صورت زیر است :class Index(*expressions, fields=(), name=None, db_tablespace=None, opclasses=(), condition=None, include=None)1-آرگومان expressions در ابتدا توضیح داده خواهد شد . این آرگومان موقعیتی است . یعنی باید استفاده شود و در مواقع مختلف (وابسته به فیلد های مدل) مقدار آن متفاوت است . مقداری که می پذیرد فیلد های شماست و با توجه به مقدار های پاس داده شده به آن , اندیس گذاری دیتابیس را انجام خواهد داد.به مثال زیر دقت کنید .Index(Lower('title').desc(), 'pub_date', name='lower_title_date_idx')مثال بالا برای شما اندیسی را روی مقدار title (با حروف کوچک) با ترتیب نزولی و روی pub_date با ترتیب صعودی به صورت پیش فرض ایجاد می کند . (شی های شما در دیتابیس بر اساس title و pub_date مرتب خواهند شد)بیایید مثالی دیگر را نیز ببینیم .Index(F('height') * F('weight'), Round('weight'), name='calc_idx')این کد برای شما اندیسی را می سازد که بر اساس نتیجه ضرب دو فیلد height و weight است . همچنین بر اساس مقدار گرد شده weight نیز کار می کند .نکته : استفاده از آرگومان name هنگامی که از expressions استفاده می کنید ,مهم است .2-آرگومان دوم fields است . شما می توانید به دو روش اندیس ها را راه اندازی کنید . روش اول این است که به جای دو آرگومان اول مقدار فیلد های خودتان را قرار دهید . ولی روش دوم که بیشتر توصیه می شود این است که از آرگومان fields استفاده کنید . این آرگومان یک لیست یا تاپل قبول می کند که درون آن نام فیلد هایی است که قرار است بر اساس آنها index شما ایجاد شود .به طور پیش فرض اندیس ها به صورت صعودی تعریف می شوند . اگر می خواهید آنها را نزولی مرتب کنید , باید یک "–" در قبل نام فیلد و در رشته خود قرار دهید . برای مثال :Index(fields=['headline', '-pub_date'])این کد اندیس را بر اساس headline (صعودی) و pub_date (نزولی) مرتب می کند .3-آرگومان سوم name است . این آرگومان همانطور که معلوم است مقدار name اندیس را مشخص می کند . مقداری که قبول می کند یک رشته است . اگر این آرگومان را تعیین نکنید ,جنگو به صورت اتوماتیک آن را تولید خواهد کرد . برای سازگاری با دیتابیس های مختلف رشته شما بیش از 30 کاراکتر نباید نداشته باشید . همچنین ابتدای آن با اعداد یا _ نباید شروع بشود .نکته :نام اندیس های شما باید unique باشد . یعنی باید منحصر به فرد باشند و دوبار استفاده نشوند . همچنین می توانید به روش زیر آنها را نیز تولید کنید :(این روش مناسب زمانی است که کلاس Meta قرار است به ارث برسد!)Index(fields=['title'], name='%(app_label)s_%(class)s_title_index')4-نام جدولی از دیتابیس که اندیس در آن ایجاد می شود را در db_tablespace تعیین می کنید . اگر اندیس شما ,فقط برای یک فیلد ایجاد شده باشد ,مقدار db_tablespace برابر با جدولی خواهد شد که فیلد هم اکنون در آن قرار دارد .اگر db_tablespace نیز تعیین نشده باشد (یا ایندکس از چند فیلد استفاده کند) ,مقدار آن از db_tablespace که در کلاس Meta مدل وجود دارد برداشته می شود . اگر این نیز تعیین نشده باشد , db_tablespace شما در همان جدول که اندیس در آن ایجاد شدند ,ایجاد خواهد شد .5-آرگومان پنجم شما opclasses است . این آرگومان مقدار نام کلاس عملگر (operator classes) در دیتابیس PostgreSQL را کنترل می کند . اگر به یک کلاس عملگر سفارشی نیاز دارید , باید برای هر فیلد در index یک کلاس را ارائه دهید .برای مثال GinIndex(name='json_index', fields=['jsonfield'], opclasses=['jsonb_path_ops']) یک اندیس از نوع gin(مربوط به مباحث دیتابیس ها) بر روی jsonfield با کلاس عملگر jsonb_path_ops خواهد ساخت .نکته : این آرگومان فقط مخصوص یک دیتابیس است و در دیتابیس های به جز PostgreSQL این آرگومان نادیده گرفته می شود .نکته : مقداردهی آرگومان name برای استفاده از opclasses اجباری است .6-اگر جدول شما بسیار بزرگ است و query یا جستجو های شما در دیتابیس یک بازه از جدول را بیشتر مورد هدف قرار می دهند , شاید بهتر باشد تا آن بازه را با Q مشخص کنید . به این ترتیب اندیس فقط در آن بازه ساخته خواهد شد و به شما در سرعت دیتابیس کمک شایانی خواهد کرد .برای این کار باید از شرط یا condition استفاده کنید . برای مثال :Condition=Q(pages_gt=400)رکورد هایی را که pages آنها بیشتر از 400 است را اندیس می کند .نکته : مقداردهی آرگومان name برای استفاده از condition اجباری است .نکته : استفاده از این آرگومان قوانین مشخصی در دیتابیس های مختلف دارد پس بهتر است حواستان باشد . برای مثال در PostgreSQL نمی توانید بدون ایجاد توابعی , condition را برای DateTimeField تعیین کنید و یا در Oracle شما نمی توانید این گونه conditionها را تعیین کنید . (این ها مباحث دیتابیس های جنگو است که باید بخوانید . در اینجا مهم این است که دیتابیس MySQL و MariaDB از این آرگومان پشتیبانی نمی کنند!)در این جلسه به بررسی مبحث ساده ی اندیس ها در جنگو پرداختیم . در جلسه بعدی به بررسی متاداده و کلاس های متا در هر مدل خواهیم پرداخت .