应使用 tinyint unsigned 或 smallint unsigned 存储位标记,而非 varchar;通过 2 的幂定义常量、按位或合并、按位与判断,并在 mysql 中直接用 & 运算符查询,兼顾性能与索引支持。

用 tinyint 或 smallint 存位标记,别用 varchar 存逗号分隔
位运算存多选状态的核心是把每个选项映射为一个独立的二进制位,比如“推送通知”=1(0001)、“邮件提醒”=2(0010)、“短信告警”=4(0100)、“站内信”=8(1000)。四个选项合起来最多 15(1111),用 tinyint unsigned 就够了——既省空间,又支持原生整数索引加速查询。
常见错误是用 varchar(255) 存 "1,3,4",这会导致:无法走索引、不能原子更新、JSON 解析开销大、容易产生脏数据(如重复值、空格、顺序混乱)。
实操建议:
- 数据库字段类型选
tinyint unsigned(最多支持 8 个选项)或smallint unsigned(最多 16 个),避免用int浪费存储 - PHP 中定义常量时直接用 2 的幂:
const NOTIFY_PUSH = 1;、const NOTIFY_EMAIL = 2;、const NOTIFY_SMS = 4; - 插入前用按位或
|合并:$flags = self::NOTIFY_PUSH | self::NOTIFY_EMAIL;
bindec() 和 decbin() 不要用在运行时判断
这两个函数是字符串和二进制之间的转换工具,适合调试输出,但不适合高频状态判断。每次调用都要做字符串解析,性能差,且易出错(比如 decbin(0) 返回 "0",长度为 1,不是空字符串)。
真正该用的是按位与 &:
- 判断是否启用推送:
($user->notify_flags & self::NOTIFY_PUSH) === self::NOTIFY_PUSH - 添加短信选项:
$newFlags = $oldFlags | self::NOTIFY_SMS; - 关闭邮件提醒:
$newFlags = $oldFlags & ~self::NOTIFY_EMAIL; - 清空所有:
$newFlags = 0;
注意:必须用 === 判断结果是否“等于”标志本身,而不是只判断是否非零——否则当多个标志共存时(如 3 即 1|2),3 & 1 是 1,但 3 & 2 也是非零,仅用 if ($flags & 2) 是对的;但若写成 if (($flags & 2) == true) 就可能被弱类型坑到。
MySQL 查询时用 & 运算符直接过滤,别查出来再 PHP 判断
数据库层就能完成的计算,别拖到 PHP 层。MySQL 支持整数位运算,WHERE notify_flags & 4 可以命中索引(前提是字段是整型且有索引),比 WHERE FIND_IN_SET('4', notify_list) 快得多,也比 JSON_CONTAINS 更轻量。
示例 SQL:
SELECT * FROM users WHERE notify_flags & 2; -- 找所有开启邮件提醒的用户 SELECT * FROM users WHERE (notify_flags & 6) = 6; -- 找同时开启邮件+短信的用户(2|4=6)
注意:(notify_flags & 6) = 6 表示“必须同时包含这两位”,而 notify_flags & 6 只要其中任一为真就成立。业务语义不同,别混淆。
兼容性提示:MySQL 4.0+ 都支持 &,但低版本不支持位运算索引优化;MariaDB 同样支持。PostgreSQL 要用 & 操作符配合 bit 类型或整型,语法一致。
扩展性差是硬伤,16 个以上选项就得换方案
用整型位运算最大瓶颈是可维护性:一旦选项超过 smallint 的 16 位,就必须升到 int(32 位)甚至 bigint(64 位),但这时常量命名、位移逻辑、迁移脚本都变复杂;更麻烦的是,新增选项必须严格追加高位,不能插在中间,否则历史数据含义全乱。
如果你已经预见到标签会动态增减、或用户可自定义标签(比如 CMS 的文章分类、SaaS 的权限组),位运算就不合适了。此时应切换为:
- 独立关联表(
user_tags),最正交、最易扩展 - JSON 字段(MySQL 5.7+ / PostgreSQL),配合生成列建索引,适合中低频查询
- Redis Set 存用户级标签,适合高并发实时判断场景
位运算是种“有约束的高效”,不是银弹。上线前想清楚:这个字段未来三年会不会加新选项?有没有运营后台要动态配置?如果答案是“会”,那就别从位运算起步。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











