一、位标志法
位标志法(bit flags):把多个选项用一个整数字段(如 INT 或 BIGINT)存储。
位标志法的优点:
- 存储效率高:只需要一个整数字段(
INT或BIGINT)。 - 写入方便:合并多个选项只需要一个整数。
- 快速判断:用位运算判断是否包含某些选项。
- 适合固定选项:如权限、状态、角色等。
位标志法的缺点:
| 不易扩展 | 最多支持 32(INT)或 64(BIGINT)个选项 |
| 查询效率低 |
位运算在大数据量下性能不如索引、 |
| 不易维护 | 查询语句不够直观,需要维护映射表 |
| 无法统计 | 无法方便地统计某个选项的使用频率 |
| 无法外键约束 | 不能建立外键引用关系 |
| 不支持动态选项 | 如果选项频繁变动,维护成本高 |
使用方法:
// 多选值合并为整数字段
public function add() {
$bitMap = [
1 => 1, // 2^0
2 => 2, // 2^1
3 => 4, // 2^2
4 => 8, // 2^3
5 => 16, // 2^4
6 => 32, // 2^5
7 => 64, // 2^6
8 => 128, // 2^7
9 => 256, // 2^8
10 => 512, // 2^9
11 => 1024, // 2^10
12 => 2048, // 2^11
13 => 4096, // 2^12
14 => 8192, // 2^13
15 => 16384, // 2^14
];
//合并多选值为一个整数字段
$typeValue = $this->combineTypes([1, 3, 6], $bitMap);
//解析整数字段为原始多选值
$parsed = $this->parseTypes($typeValue, $bitMap); // 得到 [1, 3, 6]
}
/**
* 合并多选值为一个整数字段(用于保存到数据库)
* @param array $selected
* @param array $bitMap
* @return int
*/
public function combineTypes(array $selected, array $bitMap): int {
$value = 0;
foreach ($selected as $typeId) {
if (isset($bitMap[$typeId])) {
$value |= $bitMap[$typeId]; // 按位或
}
}
return $value;
}
/**
* 解析整数字段为原始多选值(从数据库读取)
* @param int $value
* @param array $bitMap
* @return array
*/
function parseTypes(int $value, array $bitMap): array {
$result = [];
foreach ($bitMap as $typeId => $bitValue) {
if ($value & $bitValue) {
$result[] = $typeId;
}
}
return $result;
}
1527

被折叠的 条评论
为什么被折叠?



