当前位置:首页 > 问答 > 正文

树叶云数据库里讲MySQL那些位运算符怎么用,简单又实用的教程分享

树叶云数据库里分享过一个讲MySQL位运算符的教程,内容挺实在的,咱们就直接来看这些内容。

为啥要用位运算符?

来源里提到,很多时候我们设计数据库表,会遇到一些状态字段,一篇文章可能有多个属性:是不是精华(is_elite)、是不是置顶(is_top)、是不是推荐(is_recommend)、是不是热门(is_hot),最直接的做法是为每个属性设一个TINYINT字段,用0和1表示是或否。

但这样有个问题,如果属性越来越多,表里就会多出一大堆字段,查询和维护都麻烦,这时候,位运算就派上用场了,我们可以用一个整数字段(比如叫attributes)来存储所有这些状态,每一位(bit)代表一个状态,0表示否,1表示是。

  • 第0位(最右边那位)代表是不是精华:0=否,1=是
  • 第1位代表是不是置顶
  • 第2位代表是不是推荐
  • 第3位代表是不是热门

这样一个INT类型的字段(32位)就能表示32种不同的开关状态,非常节省空间,管理起来也集中。

树叶云数据库里讲MySQL那些位运算符怎么用,简单又实用的教程分享

MySQL里常用的位运算符咋用?

树叶云的教程里主要讲了四个最核心的运算符:按位或、按位与、按位异或和移位。

  1. 按位或 | :用来“添加”状态 这个运算符是把两个数的二进制位进行比较,只要有一个是1,结果就是1,我们主要用它来给某个字段“加上”一个状态。 我们要设置一篇文章为精华(假设精华对应数值1)和置顶(置顶对应数值2)。 UPDATE articles SET attributes = attributes | 1 | 2 WHERE id = 123; 这里的 1 | 2 就是进行按位或运算,1的二进制是0001,2的二进制是0010,或运算的结果是0011(十进制3),这条SQL的意思就是,不管attributes原来是什么值,都确保第0位和第1位变成1(即开启精华和置顶状态),其他位保持不变。

    树叶云数据库里讲MySQL那些位运算符怎么用,简单又实用的教程分享

  2. 按位与 & :用来“检查”或“移除”状态 按位与是只有两个位都是1,结果才是1,它最常用的场景有两个:

    • 检查是否包含某个状态:查询所有精华文章。 SELECT * FROM articles WHERE attributes & 1; 如果attributes的第0位是1(即精华),那么attributes & 1的结果肯定不等于0(在MySQL里非0即真),这样就能筛选出所有精华文章,如果想查既是精华又是置顶的文章,可以写 WHERE attributes & 1 AND attributes & 2,或者更简洁的 WHERE attributes & 3(因为1|2=3)。
    • 移除某个状态:取消一篇文章的置顶状态。 UPDATE articles SET attributes = attributes & ~2 WHERE id = 123; 这里用到了按位取反 。~2会把2(二进制0010)的每一位取反,变成...1101(前面全是1),再和原值进行按位与运算,因为“与0得0”,所以第1位(置顶位)肯定会被清零;而“与1得原值”,其他位则保持不变,这样就精准地只移除了置顶状态。
  3. 按位异或 ^ :用来“切换”状态 异或的规则是“相同为0,不同为1”,它有个很有趣的特性:一个数异或另一个数两次,会变回自己,我们可以用它来切换一个状态的开关。 想反转一篇文章的热门状态(假设热门状态用4表示,二进制0100)。 UPDATE articles SET attributes = attributes ^ 4 WHERE id = 123; 执行一次,如果原来是热门(第2位是1),1^1=0,就取消了热门;如果原来不是热门(第2位是0),0^1=1,就设为了热门,就像电灯开关一样,按一下开,再按一下关。

  4. 移位运算符 << 和 >> :用来定义状态值 移位运算符在实际更新、查询数据时用得少一点,但在定义状态常量时非常有用,我们不应该直接写1,2,4,8这样的“魔数”,而是用左移运算符来清晰表达。 定义状态常量: SELECT 1<<0 as is_elite, 1<<1 as is_top, 1<<2 as is_recommend, 1<<3 as is_hot; 这样计算出来的结果分别是1,2,4,8,但代码的可读性大大增强,一眼就能看出每个常量对应的是左移了多少位,代表哪个状态,在程序里定义常量时,也强烈推荐这样写,const IS_ELITE = 1 << 0;

实际使用时的小贴士 最后还提醒了几个要点:

  • 选择合适的数据类型:根据你需要的状态数量选,状态少于8个用TINYINT,少于16个用SMALLINT,少于32个用INT,非常多就用BIGINT。
  • 可读性问题:直接看数据库里存的数字(比如3)看不出代表什么状态,所以通常需要配合程序中的常量定义来使用,让代码清晰。
  • 索引问题:对使用了位运算的字段进行查询(比如WHERE attributes & 1)时,如果该字段上有索引,MySQL可能无法使用索引进行高效查询,尤其是在进行复杂的位组合查询时,对于查询频繁的状态,如果通常是独立使用的,单独一个字段可能是更好的选择,位运算更适合处理那些组合多变、非核心的标记性属性。

树叶云这个教程的意思就是,位运算符是MySQL里一个处理状态集的利器,用好了能简化表结构,提升灵活性,关键是掌握好 |(添加)、&(检查/移除)、^(切换)这几个核心操作,并在代码里用移位运算清晰定义常量,就能把它用得顺手。