Планирование периодической очистки базы данных на Laravel
По понятным причинам таблицы баз данных со временем имеют тенденцию к увеличению размеров. Поэтому для поддержания производительности запросов время от времени требуется их настройка.
Среди распространённых методов — создание индексов, переписывание запросов и даже перепроектирование базы данных.
Но есть и другое очевидное решение, которое также может быть применено, — это очистка данных.
В Laravel для этого есть встроенная функция, которая может быть использована двумя различными способами: Очистка
и Массовая очистка
:
Очистка
Допустим, вы хотите удалить soft-deleted пользователей по истечении 90 дней с даты удаления.
Добавьте в модель трейт Illuminate\Database\Eloquent\Prunable
и реализуйте метод prunable
, возвращающий построитель запросов Eloquent, масштабирующий запрос для получения Prunable
записей.
app/Models/User.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use Prunable;
use SoftDeletes;
/**
* Get the prunable model query.
*/
public function prunable(): Builder
{
return static::where('deleted_at', '<=', now()->subDays(90));
}
}
Пометив модели как
Prunable
, можно также определить для них метод удаления. Этот метод будет вызываться перед удалением модели.
Чтобы показать реальное применение этого метода, предположим, что у пользователя есть фотография профиля, и её также необходимо удалить из файлового хранилища:
app/Models/User.php:
/**
* Prepare the model for pruning.
*/
protected function pruning(): void
{
Storage::delete($this->picture);
}
Теперь вы можете запустить команду artisan model:prune
или запланировать её в классе App\Console\Kernel
вашего приложения.
Вы можете задать желаемый интервал, но в данном случае мы хотим осуществлять очистку данных ежедневно:
app/Console/Kernel.php:
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
$schedule->command('model:prune')->daily();
}
Когда вы выполняете команду model:prune
, она обнаруживает модели в app/Models
вашего приложения, в которых реализуется трейт Illuminate\Database\Eloquent\Prunable
.
В случае если модели находятся в другом месте, можно использовать опцию --model
:
app/Console/Kernel.php:
use App\Module\Models\User;
$schedule->command('model:prune', [
'--model' => [User::class],
])->daily();
С помощью опции --except
можно также исключить Prunable
модель, которая будет автоматически обнаружена в каталоге app/Models
:
app/Console/Kernel.php:
$schedule->command('model:prune', [
'--except' => [AnotherModel::class],
])->daily();
Иногда перед удалением необходимо узнать, сколько записей будет удалено. Это называется пробным запуском
, который можно выполнить с помощью опции --pretend
.
php artisan model:prune --pretend
Массовая очистка
При очистке записи извлекаются и обходятся как объект eloquent, удаляя их по отдельности, что вызывает события модели.
При массовой очистке выполняется один запрос, не вызывается метод pruning
, и события модели deleting
и deleted
.
app/Models/User.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use MassPrunable;
use SoftDeletes;
/**
* Get the prunable model query.
*/
public function prunable(): Builder
{
return static::where('deleted_at', '<=', now()->subDays(90));
}
}
Заключение
В этой статье вы узнали, как можно удалить ненужные данные с помощью встроенной функции Laravel и что можно удалить все сразу с помощью свойства Illuminate\Database\Eloquent\MassPrunable
или запись за записью с помощью свойства Illuminate\Database\Eloquent\Prunable
, которое позволяет определить метод pruning
для выполнения любого желаемого действия перед удалением.