You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多JSON文件读取性能问题及优化方案咨询

兄弟,你现在这个把每次变更存单独JSON文件的方案,说实话从长期来看真的不太合理,检索慢就是最直接的问题,咱们来掰扯掰扯为啥,以及Laravel里有啥更靠谱的办法。

当前方案的核心问题
  • IO性能瓶颈:文件系统处理大量小文件的效率本来就低,当变更记录多了之后,遍历文件、打开读取的开销会直线上升——尤其是你要查某条记录的所有变更时,得挨个找对应文件,耗时肯定扛不住。
  • 维护成本高:大量零散的JSON文件不好管理,备份、迁移、清理旧数据都很麻烦,而且没法直接做复杂查询(比如按时间范围筛选某类模型的变更,或者找某个用户修改的记录)。
  • 版本追踪不便:要对比某条记录的多次变更,得打开多个文件手动对比,远不如结构化存储方便。
Laravel里的更优实现方式

最推荐的是基于数据库的审计日志方案,不管是自己手动实现,还是用成熟的第三方包,都比文件方案高效太多。

1. 手动实现基础审计日志

步骤很清晰,完全贴合Laravel的Eloquent生态:

  • 首先创建审计日志表,执行这个迁移:
Schema::create('model_audits', function (Blueprint $table) {
    $table->id();
    $table->string('model_type'); // 对应模型类名,比如App\Models\Post
    $table->unsignedBigInteger('model_id');
    $table->json('old_values')->nullable(); // 变更前的字段值
    $table->json('new_values')->nullable(); // 变更后的字段值
    $table->unsignedBigInteger('user_id')->nullable(); // 操作人ID(可选)
    $table->enum('action', ['created', 'updated', 'deleted']);
    $table->timestamps();

    // 添加索引优化查询速度
    $table->index(['model_type', 'model_id']);
    $table->index('user_id');
});
  • 然后在需要追踪的模型里注册事件,比如在App\Models\Post的boot方法里:
protected static function boot()
{
    parent::boot();

    // 记录创建事件
    static::created(function ($post) {
        ModelAudit::create([
            'model_type' => get_class($post),
            'model_id' => $post->id,
            'new_values' => $post->getAttributes(),
            'action' => 'created',
            'user_id' => auth()->id(), // 可选,记录当前登录用户
        ]);
    });

    // 记录更新事件(只存变化的字段)
    static::updated(function ($post) {
        $changes = array_diff_assoc($post->getAttributes(), $post->getOriginal());
        if (!empty($changes)) {
            ModelAudit::create([
                'model_type' => get_class($post),
                'model_id' => $post->id,
                'old_values' => $post->getOriginal(array_keys($changes)),
                'new_values' => $changes,
                'action' => 'updated',
                'user_id' => auth()->id(),
            ]);
        }
    });

    // 记录删除事件
    static::deleted(function ($post) {
        ModelAudit::create([
            'model_type' => get_class($post),
            'model_id' => $post->id,
            'old_values' => $post->getAttributes(),
            'action' => 'deleted',
            'user_id' => auth()->id(),
        ]);
    });
}

之后查询某条记录的变更历史就简单到离谱:

$post = Post::find(1);
$history = ModelAudit::where('model_type', get_class($post))
    ->where('model_id', $post->id)
    ->orderBy('created_at', 'desc')
    ->get();

数据库有索引加持,查询速度快得飞起,还能轻松做各种筛选、排序。

2. 用成熟的第三方包(更省心)

如果不想自己写重复代码,直接用spatie/laravel-activitylog这个包——Laravel生态里最流行的审计日志工具之一,开箱即用:

  • 安装包:
composer require spatie/laravel-activitylog
  • 发布迁移文件并执行:
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="migrations"
php artisan migrate
  • 在需要追踪的模型里添加LogsActivity trait,配置要记录的字段:
use Spatie\Activitylog\Traits\LogsActivity;

class Post extends Model
{
    use LogsActivity;

    // 配置要记录的字段,默认记录所有字段变更
    protected static $logAttributes = ['title', 'content'];
    // 只记录有变化的字段
    protected static $logOnlyDirty = true;
    // 自定义日志名称,方便区分不同模型
    protected static $logName = 'post';
}

之后所有变更都会自动存入activity_log表,查询历史也很简单:

$post = Post::find(1);
$history = $post->activities()->orderBy('created_at', 'desc')->get();

这个包还支持自定义日志内容、关联用户、批量清理旧日志等功能,省心又省力。

总结

当前的单JSON文件方案只适合非常小规模的场景,一旦数据量上来,检索和维护都会出问题。Laravel里用数据库存储审计日志才是更合理的选择,不管是手动实现还是用第三方包,都能解决你现在的检索慢问题,而且扩展性更强。

内容的提问来源于stack exchange,提问作者Kanth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:46:18