首页 > 数据库 >数据库中利用二进制实现多个布尔属性的增删改查

数据库中利用二进制实现多个布尔属性的增删改查

时间:2024-03-19 15:16:17浏览次数:27  
标签:false queryVal 二进制 改查 二进制位 oldVal 增删 true 属性

需求背景

业务场景中经常需要一些布尔型的属性来标记数据状态, 如果每个属性值都新增一个数据库字段来保存会造成空间上的浪费, 在工作中进行建模设计时难免会想到用二进制来节省空间, 以整形32位为例, 去除最高位的符号位总共可以用来保存31个布尔属性值。

实现细节

为方便讲解, 这里统一用8位二进制数字进行举例说明, 0表示false、1表示true, 从低到高依次对应ABCDEFGH这八个布尔属性值。

  • 每个属性值对应固定某个二进制位, 声明一个常量哈希表声明指定, 例如AB属性分别对应的就是'00000001'和'00000010';
  • 根据对应的二进制位数值bitVal更新属性值:
    • 通过 oldVal & bitVal 将属性值设为true, 如 setA(true) 对应 oldVal = oldVal & '00000001'
    • 通过 oldVal & ~bitVal 将属性值设为false, 如 setA(false) 对应 oldVal = oldVal & '11111110'
  • 因为业务场景中需要同时查询多个属性部分为true且部分为false的数据, 实现时需要借助另一个变量值来标记具体哪些二进制位参与了数据筛选:
    • 假设需要查询AC为true且BF为false的数据, 即用于筛选的对象变量依次调用 setA(true)、setC(true)、setB(false)、setF(false);
    • 属性变量queryVal记录指定为true或false后的值, 即 \(queryVal = '00000101'\);
    • 属性变量bitCompared记录哪些属性对应二进制位要参与筛选, 即 \(bitCompared = '00100111'\);
    • 筛选的SQL子句为 t.val ^ #{queryVal} & #{bitCompared} = 0
    • 满足期望的数据与queryVal值的异或结果会将ABCF对应四个二进制位置零, 再和bitCompared进行与操作后就将其它不需要关注的属性二进制位也置零了;
    • 筛选子句也可以用 t.val & #{bitCompared} = #{queryVal} 实现, 主要是看对位运算的理解运用。

总结

  • 优点是节省数据库单表字段数量节省空间;
  • 缺点是查询时子句有位运算无法再利用索引, 需要看业务场景中有没有诸如时间区间等其它主索引字段辅助减少筛选数据量, 否则影响查询效率;
  • 这算是比较常见的二进制知识在工作中的应用, 属于能想到就简单巧妙但是想不到就真挠头的典型位运算技巧, 简单记录一下。

标签:false,queryVal,二进制,改查,二进制位,oldVal,增删,true,属性
From: https://www.cnblogs.com/coding-memory/p/18082861

相关文章

  • JAVA--数据库(增删改)
    增(INSERT)#给指定字段添加数据insertinto表名(字段1,字段2...)values(值1,值2...);给全部字段添加数据insertinto表名values(值1,值2...);批量添加数据insertinto表名(字段1,字段2...)values(值1,值2...),(值1,值2...),(值1,值2...);   insertinto......
  • 【PostgreSQL PGCE-091题目解析14】PostgreSQL中使用CONCURRENTLY选项创建索引时,允许
    本文为云贝教育刘峰(微信:yunbee_DBA)原创,请尊重知识产权,转发请注明出处,不接受任何抄袭、演绎和未经注明出处的转载。PostgreSQL中使用CONCURRENTLY选项创建索引时,允许增删改数据表。A.正确B.错误参考答案:A解析:我们知道,PG是有行级琐的,在创建索引的时候,会在行上加琐......
  • 查看宝塔mysql二进制文件 mysqlbinlog
    mysqlbinlog执行文件位置/www/server/mysql/binmysql-bin二进制日志位置/www/server/data/#/www/server/data/mysql-bin.000060把二进制导出为.sql文件#建议/www/server/data/mysql-bin.000060文件cp到mysqlbinlog文件执行目录并设置权限为www755./mysqlbinlogmysql-......
  • 67. 二进制求和c
    特好的题目,进制转化就刷它。 voidreverse(char*s){intn=strlen(s);inthead=0,tail=n-1;while(head<=tail){chart=s[head];s[head]=s[tail];s[tail]=t;head++;tail--;}}intmax(inti,intj){i......
  • 二进制部署 Prometheus+Alertmanager+Grafana
    从官网手动安装Prometheus采集、存储数据Grafana用于图表展示alertmanager用于接收Prometheus发送的告警信息node-exporter用于收集操作系统和硬件信息的metrics二进制部署#切换到root用户sudo-i#创建一个专门的prometheus用户:useradd-M-s/usr/sbin/nologi......
  • LeetCode[题解] 2864. 最大二进制奇数
    题目给你一个二进制字符串s,其中至少包含一个'1'。你必须按某种方式重新排列字符串中的位,使得到的二进制数字是可以由该组合生成的最大二进制奇数。以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。注意返回的结果字符串可以含前导零。示例1:输入:s......
  • 多重背包详解,二进制优化、单调队列优化
    文章目录零、前言一、多重背包初步1.1问题描述1.2朴素算法二、朴素算法的优化策略2.1二进制优化2.1.1算法思想2.2二进制优化的正确性证明2.3代码实现2.2单调队列优化2.2.1算法思想2.2.2代码实现2.3、总结三、OJ练习3.1P1776宝物筛选3.1.1原题链接3.1.2思路分析3.1.3......
  • leetcode: 2861. 最大二进制奇数
    给你一个 二进制 字符串 s ,其中至少包含一个 '1' 。你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组合生成的 最大二进制奇数 。以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。注意 返回的结果字符串 可以 含前导零。示例......
  • 2864.最大二进制奇数
    给你一个 二进制 字符串 s ,其中至少包含一个 '1' 。你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组合生成的 最大二进制奇数 。以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。注意 返回的结果字符串 可以 含前导零。......
  • LeetCode每日一题[C++]-2864.最大二进制奇数(贪心)
    题目描述给你一个 二进制 字符串 s ,其中至少包含一个 '1' 。你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组合生成的 最大二进制奇数 。以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。注意 返回的结果字符串 可以 含前......