Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти
Інше
Події Про нас

Статті за тегом «Оптимізація»

Статті, новини, туторіали та переклади від учасників спільноти

No results.
Tips 02 липня 2026

Уникати select(*) в продакшені

Завантаження всіх колонок? Витрачається пам'ять та пропускну здатність.

Обирай тільки колонки які реально використовуєш. Менший об'єм даних. Швидші запити. Менше пам'яті.

Прихована ціна:

Текстові колонки можуть бути величезними. JSON колонки ще більші. Timestamps які можливо не потрібні.

Перевага індексу:

Запити з меншою кількістю колонок можуть використовувати covering індекси.

Порада: Профілюй з EXPLAIN щоб побачити чи запит використовує index-only scan.

// ПОГАНО: Завантажує все включаючи великі текстові поля
$posts = Post::where('published', true)->get();

// ДОБРЕ: Тільки потрібні колонки
$posts = Post::select('id', 'title', 'slug', 'published_at')
    ->where('published', true)
    ->get();

// Приклад API відповіді
public function index()
{
    return Post::select([
            'id',
            'title',
            'slug',
            'excerpt',
            'published_at',
        ])
        ->with('author:id,name,avatar')
        ->where('published', true)
        ->paginate(20);
}

// Dropdown/автозаповнення
$users = User::select('id', 'name')
    ->where('active', true)
    ->get();

// Зі зв'язками - вказуй колонки для обох
$posts = Post::select('id', 'title', 'author_id')
    ->with('author:id,name')
    ->get();
Filament Optimization
Новини 27 червня 2026

Допоможіть зробити Filament швидшим!

Команда Filament запускає бета-версії v4.12 та v5.7 з масштабними оптимізаціями продуктивності. Розробники можуть вже сьогодні протестувати нову версію у своїх додатках та поділитися результатами з командою.

Tips 26 червня 2026

remember() - кешування результатів запитів

Той самий запит виконується 100 разів за секунду. База даних потіє.

Закешування результатів. Звернись до бази один раз, обслуговуй з кешу.

Спосіб Laravel:

Використовувати remember() на запитах. Автоматично кешує результати з тегами.

Коли кешувати:

  • Дані змінюються рідко (категорії, налаштування)
  • Дорогі запити (join'и, агрегація)
  • Сторінки з високим трафіком

Інвалідація кешу:

Очищати кеш коли дані змінюються використовуючи події моделі.

Порада: Використовувати короткий час кешування (5-15 хвилин) для даних що змінюються іноді.

// ПОГАНО: Звертається до бази кожен раз
$categories = Category::all();

// ДОБРЕ: Кеш на 1 годину
$categories = Cache::remember('categories', 3600, fn() =>
    Category::all()
);

// Використання query builder
$activeUsers = User::where('active', true)->remember(600)->get(); // 10 хвилин

// Кеш з тегами
$posts = Cache::tags(['posts', 'homepage'])
    ->remember('posts.featured', 3600, function () {
        return Post::where('featured', true)->get();
    });

// Інвалідація при події моделі
class Post extends Model
{
    protected static function boot()
    {
        parent::boot();
        static::saved(function () {
            Cache::tags('posts')->flush();
        });
    }
}
// Вічний кеш (ручна інвалідація)
$settings = Cache::rememberForever('settings', fn() =>
    Setting::pluck('value', 'key')
);

// Ключ кешу з параметрами
$userId = 5;
$posts = Cache::remember("user_{$userId}_posts", 3600,
    fn() => Post::where('user_id', $userId)->get()
);

// Умовне кешування
if (config('cache.enabled')) {
    $data = Cache::remember('key', 3600, fn() => expensiveQuery());
} else {
    $data = expensiveQuery();
}

// Очистити конкретний кеш
Cache::forget('categories');

// Очистити тегований кеш
Cache::tags(['posts'])->flush();

// Перевірити чи закешовано
if (Cache::has('categories')) {
    $categories = Cache::get('categories');
}
Як Laravel News забезпечив кешування на краю мережі за допомогою Fast Laravel
Новини 18 червня 2026

Як Laravel News забезпечив кешування на краю мережі за допомогою Fast Laravel

Команда Laravel News поділилася досвідом впровадження edge-кешування на високонавантаженому сайті з динамічним контентом. Використовуючи курс Fast Laravel та Cloudflare, вони досягли 70% кешованих запитів і значно пришвидшили роботу сайту.

Tips 31 березня 2026

exists() vs count() - розумна перевірка

Перевірка чи користувач має пости? Використання $user->posts->count() > 0 завантажує всі пости.

exists() зупиняється на першому збігу. Набагато швидше.

Різниця:

  • count() підраховує всі записи
  • exists() зупиняється коли знаходить перший

Вплив на продуктивність:

З 10,000 постів - count() завантажує всі, exists() знаходить один і зупиняється.

Порада: Використання exists() для булевих перевірок, count() тільки коли потрібне фактичне число.

// ПОГАНО: Завантажує всі пости, рахує їх
if ($user->posts->count() > 0) {
    echo "Користувач має пости";
}

// ДОБРЕ: Зупиняється на першому пості
if ($user->posts()->exists()) {
    echo "Користувач має пости";
}

// Перевірка чи зв'язок порожній
if ($user->posts()->doesntExist()) {
    echo "Пости не знайдено";
}

// Рівень запиту
if (Post::where('published', true)->exists()) {
    // Принаймні один опублікований пост існує
}

// Коли справді потрібна кількість
$postCount = $user->posts()->count();
echo "Користувач має {$postCount} постів";

// Перевірка порожнього на завантаженому зв'язку
if ($user->posts->isEmpty()) {
    // Вже завантажено, без додаткових запитів
}
Tips 27 березня 2026

whereIn() з великими масивами - пастка пам'яті

Передавання 10,000 ID в whereIn()? Рядок запиту стає величезним.

MySQL має ліміти розміру запиту. PHP використовує тонни пам'яті.

Кращий підхід:

Використовувати підзапит або тимчасову таблицю для великих наборів даних.

Продуктивність:

  • whereIn() з 100 елементами - нормально
  • whereIn() з 10,000 елементами - проблема
  • Підзапит - константна пам'ять

Порада: Якщо масив має більше 1000 елементів, розглянь використання підзапиту або chunking.

// ПОГАНО: Великий масив в whereIn
$userIds = range(1, 10000); // 10k ID
$users = User::whereIn('id', $userIds)->get();
// Величезний запит, високе використання пам'яті

// ДОБРЕ: Використовувати підзапит
$activeUserIds = DB::table('user_activity')
    ->where('last_login', '>', now()->subDays(30))
    ->select('user_id');

$users = User::whereIn('id', $activeUserIds)->get();

// Альтернатива: Join
$users = User::join('user_activity', 'users.id', '=',
    'user_activity.user_id')
    ->where('user_activity.last_login', '>', now()->subDays(30))
    ->select('users.*')
    ->get();

// Розділяй великі операції
$userIds = range(1, 10000);
collect($userIds)->chunk(500)->each(function ($chunk) {
    User::whereIn('id', $chunk)->update(['notified' => true]);
});
Tips 14 березня 2026

Route Caching - миттєвий приріст швидкості

Файл маршрутів завантажується при кожному запиті. З 500+ маршрутами це багато.

Кешування маршрутів компілює маршрути в один закешований файл. В 10 разів швидше.

Як використовувати:

Запустити php artisan route:cache після деплою. Маршрути завантажуються з кешу, а не з файлів.

Важливі обмеження:

Closure маршрути НЕ працюють з кешуванням. Виникнуть помилки. Всі маршрути повинні використовувати синтаксис controller@method.

Найкраща практика:

  1. Ніколи не використовувати closures в маршрутах - завжди контролери
  2. Кешувати маршрути тільки в продакшені
  3. Очищати кеш коли додаються нові маршрути
  4. Додати до скрипту деплою

Порада: Поєднувати з config:cache та view:cache для максимальної продуктивності.

// ПОГАНО: Не працює з route:cache
Route::get('/users', function () {
    return User::all();
});

// ДОБРЕ: Працює з кешуванням
Route::get('/users', [UserController::class, 'index']);

// Команди деплою
php artisan config:cache  // Кешувати конфіг
php artisan route:cache   // Кешувати маршрути
php artisan view:cache    // Кешувати view

// Розробка - очистити всі кеші
php artisan optimize:clear

// Перевірити що маршрути закешовані
php artisan route:list
// Має завантажуватись миттєво якщо закешовано

// В composer.json - авто-кеш після деплою
"scripts": {
    "post-autoload-dump": [
        "@php artisan route:cache"
    ]
}