mysql存储比特位

一、介绍

1、实用性

项目中可能有很多开关,如果存成K-V类型的,存储比较占空间,根据key来批量查询也耗时。开关只有两个值,true或false,这和java的bit(0或1)非常类似,因此可以用一个bit来表示一个开关。如果数据库一个字段只存储一个bit,仍然解决不了上述问题,因此可以把多个比特位放在一起。如用一个bigint字段来存储比特位,bigint转成二进制最多可以存储62个bit,这样查询一个字段就能获取到62个开关。

2、基础

符号 描述 运算规则
& 两个位都为1时,结果才为1
| 两个位都为0时,结果才为0
^ 异或 两个位相同为0,相异为1
~ 取反 0变1,1变0
<< 左移 各二进位全部左移若干位,高位丢弃,低位补0
>> 右移 各二进位全部右移若干位,高位补0或符号位补齐
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

3、实现 

CREATE TABLE bits_table (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id varchar(20),
    bit_value BIGINT UNSIGNED
);

关于bit的更新与查询,有两种方法,整体操作(int)或者按位操作bit。

默认值问题:我们一般认为0代表false 1代表true,如果某一位bit默认值需要为true,也有两种方法:刷数据初始化值都刷成1;或者在代码层面做标记,查询/更新做个取反。

二、java代码操作整体Long字段

更新时可以先在java代码使用位运算算出整个bigint,再更新这个bigint字段;

查询也可以查出整个bigint,在java代码中使用位运算计算某一位的值。

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

public class BitUtil {
    public static int setBit(int options, int bitIndex) {
        int val = 1 << bitIndex;
        return options | val;
    }

    public static int unsetBit(int options, int bitIndex) {
        int val = 1 << bitIndex;
        return options & (~ val);
    }

    public static boolean isBitSetted(int options, int bitIndex) {
        int val = 1 << bitIndex;
        return (options & val) == val;
    }

    public static boolean isBitUnSetted(int options, int bitIndex) {
        int val = 1 << bitIndex;
        return (options & val) == 0;
    }

    public static boolean isSetted(long options, long bit) {
        return (options & bit) == bit;
    }

    public static long set(long options, long bit) {
        return options | bit;
    }
    public static long unset(long options, long bit) {
        return options & (~bit);
    }

    public static long set(long options, long bit, boolean flag) {
        if (flag) {
            return set(options, bit);
        } else {
            return unset(options, bit);
        }
    }
    public static boolean isSet(long options, long bit) {
        return (options & bit) == bit;
    }

    public static void main(String[] args) {

        UserDTO userDTO = getByUserId("zs");
        long options = userDTO.getOptions;
        //获取第7个开关的值
        long index = 1L << 6;
        boolean switchValue = BitUtil.isSet(options, index);
        //设置第7个开关
        switchValue = !switchValue;
        options = BitUtil.set(
                options,
                index,
                switchValue);
        userDTO.setOptions(options);
        updateUser(userDTO);
    }
}

三、mysql按位操作

还是上面的表,也可以写SQL按位操作

1、插入

-- 1、插入一个8 位的 BIT 值
INSERT INTO bits_table (bit_value) VALUES (B'10101010');

2、查询并格式化为二进制输出

-- 2、查询并格式化输出,将 BIGINT 转换为 64 位的二进制字符串
SELECT 
    id,
    bit_value,
    CONCAT('b', LPAD(BIN(bit_value), 64, '0')) AS formatted_bit_value
FROM 
    bits_table;

查询结果:

 CONCAT('b', LPAD(BIN(bit_value), 64, '0')) 用于将 bit_value 转换为一个以 'b' 开头的 64 位二进制字符串&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_t_y_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值