array_unique()最快但会将0、false、""、null视为相同且保留首键;多维数组需用键名唯一性技巧;序列化去重有风险;大数据量应优先SQL层DISTINCT/GROUP BY。

array_unique() 直接去重但要注意类型和键名
array_unique() 是最常用也最快的去重方式,但它内部会把所有值转成字符串比较,导致 0、false、""、null 被视为相同;同时它保留第一个出现的键名,后续重复项的键会被丢弃。
如果你的数组是纯数值或字符串且不关心键名连续性,直接用就行:
$data = [0, '0', false, '', null, 1]; $result = array_unique($data); // 实际只留 0 和 1
若需保持数字索引连续,必须补上 array_values():
- 不加
array_values():键名残留(如[0 => 0, 5 => 1]) - 加了之后:
[0 => 0, 1 => 1],适合后续 for 循环或 JSON 输出
多维数组按指定字段去重不能靠 array_unique()
array_unique() 对多维数组默认无效——它只比较序列化后的字符串,但 PHP 8.1+ 虽支持 SORT_STRING 等 flag,仍无法精准控制“按 id 或 email 字段去重”。真要这么做,得自己维护一个已见标识集合。
立即学习“PHP免费学习笔记(深入)”;
推荐用键名唯一性技巧,比 in_array() 快得多:
$seen = [];
$uniqueData = [];
foreach ($users as $user) {
$key = $user['email']; // 或 md5($user['name'] . $user['phone'])
if (!isset($seen[$key])) {
$seen[$key] = true;
$uniqueData[] = $user;
}
}
- 用
isset()判断比in_array()快一个数量级,尤其数据量 > 1000 时 - 注意
$key必须是 string 或 int;如果字段可能为null或数组,先做strval()或json_encode() - 这种写法保留首次出现的记录;想留最后一次,把赋值逻辑移到判断之后即可
用 serialize() + array_unique() 处理全结构去重有风险
有人用 array_map('serialize', $arr) 再去重,最后 array_map('unserialize', ...),看似能处理任意嵌套结构。但实际隐患不少:
- PHP 版本升级可能导致
serialize()格式微变,反序列化失败 - 含资源句柄、闭包、对象(未实现
__sleep)的数组直接报错 - 浮点数精度、NaN、INF 在序列化后可能被标准化,造成误判重复
- 性能差:每个元素都要序列化+反序列化,1000 条数据慢 3–5 倍于键名法
除非你明确知道数据结构干净且稳定,否则别碰这招。
DISTINCT 和 GROUP BY 应该优先在 SQL 层做
从数据库查出 10 万行再在 PHP 里去重,是典型的“把数据库当存储,把 PHP 当数据库”错误。哪怕只是加个 DISTINCT,性能差距也可能是百倍。
比如你要去重用户邮箱:
- ❌ 错误:查出全部
SELECT email, name FROM users,再 PHP 去重 - ✅ 正确:
SELECT DISTINCT email, MAX(name) as name FROM users GROUP BY email - 索引必须建在
GROUP BY字段上,否则 MySQL 会触发 filesort,越查越慢
真正需要 PHP 去重的场景,其实是聚合后的小结果集(比如分页后每页 20 条),或者无法修改 SQL 的遗留系统。别本末倒置。



















