بهره وری دیتابیس یک پروژه لاراولی را چگونه بسنجیم؟

بهره وری دیتابیس یک پروژه لاراولی را چگونه بسنجیم؟

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

قصد داریم در چند مقاله مواردی را مطرح کنیم که به بهبود بهره وری برنامه هایی که با فریم ورک لاراول توسعه داده می شوند، کمک می کند. در اولین قسمت آن در مورد شاخص های بهروری دیتابیس صحبت می کنیم.

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

این پکیج مخصوص برنامه های لاراولی توسعه داده شده است و پارامتر های متفاوتی در برنامه شما را نشان می دهد. برای دیدن قابلیت های این پکیج، پروژه را دانلود کنید. 

در این برنامه یک صفحه داریم که لیست تمام کاربرها به همراه شرکتی که در آن کار می کنند را نشان می دهیم. توسط seeder ای که در این پروژه وجود دارد 1000 شرکت که هر کدام 50 کاربر دارند را در دیتابیس قرار می دهیم (درمجموع 50 هزار کاربر).

همچنین درون فایل composer.json این پروژه پکیج laravel-debugbar را در بخش require-dev قرار داده ایم. توجه کنید که هرگز این پکیج در محیط production برنامه شما اجرا نشود. زیرا اطلاعات حساسی را به کاربران عادی برنامه نشان می دهد که ممکن است باعث آسیب پذیر شدن برنامه شما بشود.

پس از نصب پروژه و اجرای دستور php artisan migrate:fresh –seed می توانید به مسیر "/" درخواست بدهید و لیست کاربر ها را مشاهده کنید. 

1-مدت زمان درخواست

همانطور که مشاهده می کنید نوار debugbar در پایین صفحه وجود دارد. اولین معیاری که باید آن را در نظر بگیریم مدت زمان درخواست است.

این پارامتر به ما نشان می دهد چه مدت بارگذاری این صفحه طول کشیده است. در نظر داشته باشید که اکنون این عدد به دلیل اجرای برنامه روی سیستم local، 146 میلی ثانیه است و هنگامی که روی سرور آن را اجرا کنیم چیزی حدود 30 میلی ثانیه خواهد بود. هنگام اجرا روی سرور بهتر است این عدد زیر 200 میلی ثانیه (در بهترین حالت زیر 100 میلی ثانیه) باشد.

2-تعداد کوئری ها

معیار بعدی که باید در نظر بگیریم بخش کوئری ها است. اصلی ترین موردی که در این بخش همیشه به آن نگاه می کنیم تعداد کوئری های اجرا شده است. این تعداد به طور معمول مشکلات n+1 موجود در برنامه را به ما نشان می دهد.

برای مثال به کنترلر UserController می رویم و کد eagerload شدن رابطه company را کامنت می کنیم.

<?php

namespace App\Http\Controllers;

use App\User;

class UsersController extends Controller
{
    public function index()
    {
        $users = User::query()
            // ->with('company')
            ->simplePaginate();

        return view('users', ['users' => $users]);
    }
}

اکنون اگر صفحه کاربرها را refresh کنیم تعداد کوئری ها از 2 به 16 تغییر می کند. زیرا لاراول، شرکت مربوط هر کاربر را توسط یک کوئری جدا از دیتابیس می خواند.

تشخیص ایراد های این گونه، هنگام توسعه برنامه اهمیت زیادی دارد. زیرا به طور معمول اگر این مشکل ها به فضای production برنامه برسند، به دلیل وجود داده بیشتر، وضعیت بدتری ایجاد می کنند.

4-زمان اجرای کوئری ها

پارامتر بعدی که باید به آن نگاه کنیم، زمان اجرای هر کوئری است. برنامه ای که تنها یک کوئری دارد اما آن کوئری کند است، همچنان در بهره وری دارای مشکل است.

برای مثال، می خواهیم کاربران برنامه را بر اساس نام، مرتب کنیم. این کار را به آسانی با اضافه کردن orderBy به کوئری خود انجام می دهیم.

 

<?php

namespace App\Http\Controllers;

use App\User;

class UsersController extends Controller
{
    public function index()
    {
        $users = User::query()
            ->with('company')
            ->orderBy('name')
            ->simplePaginate();

        return view('users', ['users' => $users]);
    }
}

اکنون اگر به صفحه کاربران برگردیم و refresh کنیم، مشاهده می کنیم که لیست کاربران بر اساس نام مرتب شده اند.

با دقت به زمان اجرای کوئری ها می بینیم که زمان آن نسبت به قبل حدود 3 برابر شده است.

این تغییر در زمان اجرای کوئری ها به ما نشان می دهد که برای ستون name در جدول users برنامه نیاز به اضافه کردن index است.

ابتدا یک Migration ایجاد می کنیم.

php artisan make:migration add_name_index_to_users

سپس ستون name را index می کنیم.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddNameIndexToUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->index('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropIndex('users_name_index');
        });
    }
}

و دستور php artisan migrate را می زنیم تا index در دیتابیس پروژه اضافه شود. 

اکنون به صفحه کاربران بر می گردیم و صفحه را refresh می کنیم.

همانطور که مشاهده می کنید زمان اجرای کوئری ها به حالت قبل برگشته است (از 60 میلی ثاتیه به 28 میلی ثانیه).

5-مصرف مموری

معیار بعدی که باید به آن نگاه کنیم میزان مصرف مموری است. این پارامتر ارتباط مستقیم با بهره وری برنامه هایی که می نویسیم دارد. در صورتی که این میزان از حد معمول خود بالاتر برود نشانه وجود یک مشکل در بهره وری برنامه ما است. میزان معمول این پارامتر در سرور 4 تا 5 مگابایت و روی سیستم های local 15 تا 16 مگابایت است.

مشکلی که این معیار دارد این است که به سختی می توانیم ایراد برنامه را توسط آن تشخیص بدهیم. برای مثال اگر مصرف مموری از 4 به 6 مگابایت تغییر کند به احتمال زیاد اهمیتی به آن داده نمی شود زیرا این عدد یک نتیجه کلی از عملکرد برنامه ما است و به بخش خاصی از برنامه اشاره نمی کند. به همین دلیل برای بررسی بهره وری دیتابیس پروژه از معیار بهتری استفاده می کنیم. سربرگ Models در debugbar معیار خوبی برای سنجش مصرف مموری لایه دیتابیس پروژه ها است.

در این سربرگ تمام مدل هایی که لاراول از دیتابیس خوانده است را می توانید ببینید.

همانطور که می بینید در پروژه ما 16 کاربر و 16 شرکت از دیتابیس فراخوانی شده اند.

برای مثال به مدل Company در پروژه می رویم و property با نام with به آن اضافه می کنیم تا همه کاربران یک شرکت، هر بار که آن شرکت از دیتابیس خوانده می شود eagerload شوند.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Company extends Model
{
    protected $with = ['users'];

    public function users()
    {
        return $this->hasMany(User::class);
    }
}

اکنون اگر صفحه کاربران را refresh کنیم، تعداد مدل های فراخوانی شده متفاوت است.

همانطور که می بینید تعداد کاربران خوانده شده از دیتابیس از 16 به 816 تغییر پیدا کرد که تفاوت بسیار زیادی است. در صورتی که مصرف مموری تنها 2 مگابایت افزایش داشت. به همین دلیل، قبل تر گفته شد که معیار مموری مصرف شده دقیق نیست و به خوبی نشان نمی دهد که در برنامه ما مشکلی وجود دارد در صورتی که با نگاه به سربرگ Models به خوبی می بینیم که مقدار زیادی مدل فراخوانی شده که ما هیچ استفاده ای از آن نداریم.

6-جمع بندی

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

از بهترین نوشته‌های کاربران سکان آکادمی در سکان پلاس


online-support-icon