Laravel-admin搜索慢或查不到数据主因是MySQL索引未建对:filter中equal、like、between及外键字段须建对应索引,utf8mb4需设defaultStringLength(191),并用SHOW INDEX和EXPLAIN验证生效。

laravel-admin搜索慢或查不到数据,大概率是数据库索引没建对
不是代码写错了,也不是配置漏了,而是 MySQL 没法高效走索引。Laravel-admin 的 filter() 默认用 LIKE 或 = 查询,如果字段没索引、索引类型不对、或者查询条件破坏了索引使用规则,就会全表扫描——几千条数据就卡,上万条直接超时。
哪些字段必须加索引?看你的 filter 怎么写的
打开你 Grid 的 filter 逻辑,逐行检查 where 条件里出现的字段:
-
equal('status')→status字段必须有单列索引 -
like('title')→title字段建议加 B-tree 索引(LIKE 'xxx%'可用,'%xxx'不可用) -
between('created_at')→created_at必须有索引,且最好单独建,别塞进复合索引后半段 - 关联查询如
where('category_id')→ 外键字段category_id必须有索引(Laravel 迁移里没自动加!)
特别注意:MySQL 对 utf8mb4 字段建索引有长度限制,默认 string(255) 超长会报 Specified key was too long 错误,导致索引创建失败但无提示。
怎么验证索引是否生效?别只看 migration 是否跑过
Migration 成功 ≠ 索引真的建上了。执行以下三步交叉验证:
- 查表结构:
SHOW INDEX FROM admin_users;(把表名换成你实际的)确认目标字段出现在Key_name列里 - 看执行计划:
EXPLAIN SELECT * FROM admin_users WHERE username = 'admin';,重点看key列是否显示索引名,rows是否远小于总行数 - 模拟 filter 查询:
SELECT * FROM your_table WHERE name LIKE 'test%';,如果EXPLAIN显示type: ALL,说明索引完全没被用上
常见陷阱:在 name LIKE '%test' 这种左模糊场景下,B-tree 索引失效,此时得换全文索引或改用 Scout + Meilisearch。
加索引的迁移写法,避开字符集坑
不要直接 $table->index('name'),尤其字段是 string(191) 以上时。正确写法:
php artisan make:migration add_index_to_posts_title_and_status
<p>// 在 up() 方法里:
Schema::table('posts', function (Blueprint $table) {
$table->index('title', 'idx_posts_title'); // 显式命名,方便后续删
$table->index('status', 'idx_posts_status');
$table->index(['status', 'created_at'], 'idx_posts_status_created'); // 复合索引注意顺序
});
</p>
如果遇到 Specified key was too long,不是改字段长度,而是在 AppServiceProvider::boot() 加:Schema::defaultStringLength(191);,再重跑迁移。
复合索引字段顺序不能错——比如 filter 同时用了 status 和 created_at,但经常只查 status = 'draft',那 status 必须放复合索引第一位,否则单查 status 时索引无效。











