返回顶部
首页 > 资讯 > 精选 >如何使用bitset实现毫秒级查询
  • 764
分享到

如何使用bitset实现毫秒级查询

bitset 2023-05-31 00:05:06 764人浏览 泡泡鱼
摘要

这篇文章主要为大家展示了“如何使用bitset实现毫秒级查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用bitset实现毫秒级查询”这篇文章吧。bitset介绍看jdk中的解释简直一头

这篇文章主要为大家展示了“如何使用bitset实现毫秒级查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用bitset实现毫秒级查询”这篇文章吧。

bitset介绍

jdk中的解释简直一头雾水,用我自己的理解概括一下

bitset的内部实现是long数组
2.set中每一个位的默认值为false(0)
3.bitset长度按需增长
4.bitset非线程安全

bitset关键方法分析

public void set(int bitIndex) { if (bitIndex < 0)  throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); int WordIndex = wordIndex(bitIndex); expandTo(wordIndex); words[wordIndex] |= (1L << bitIndex); // Restores invariants checkInvariants();}

设置指定“位”为true,bitIndex参数为非负整数。假设我们执行以下代码,观察上面代码中worIndex,words[wordIndex]值的变化

BitSet bs = new BitSet()bs.set(0);bs.set(1);bs.set(2);bs.set(3);bs.set(4);
bitIndexwordIndexwords[wordIndex]words[wordIndex]二进制表示
0010001
1030011
2070111
30151111
40310001 1111

通过上表,我们可以很清晰的根据bitIndex和words[wordIndex]二进制值的对应关系,得到一个结论,即:bitset中每一个long可以表示64个非负整数在bitSet中存在与否。例如:0001可以表示整数0在bitset中存在,1111可以表示整数3,2,1,0在bitset中存在。

进入正题,实现bitset毫秒级查询

想象一个场景,我们有一张user表

CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `address` varchar(255) NOT NULL comment '地址', `gender` varchar(10) NOT NULL comment '性别', `age` varchar(10) NOT NULL, PRIMARY KEY (`uid`)) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

假设我们要查询“北京市18岁的女生”,那么对应的sql如下:

select * from `user` where address='北京' and age='18' and gender='girl';

如何使用bitset实现同样的查询呢?

将user表数据加载进内存中

为user表建立address,age,gender维度的bitset索引

根据索引查询数据

1.将user表数据加载进内存中

将user表从数据库读取出来存入List

User实体类:

public class User implements Cloneable { private String name; private String address; private String gender; private String age; @Override public String toString() {  return "User [name=" + name + ", address=" + address + ", gender=" + gender + ", age=" + age + "]"; } @Override public User clone() {  User user = null;  try {   user = (User) super.clone();  } catch (CloneNotSupportedException e) {   e.printStackTrace();  }  return user; } //省略get set 方法。。。

2.建立索引

创建bitset索引模型类

public class BitSetIndexModel { private String type;//索引类型:address,age,gender private ConcurrentHashMap<String, Integer> map;//索引类型和bitSet在bsList中下标的映射关系 private List<String> list;//索引类型的值集合,例如gender:girl,boy private List<BitSet> bsList;//bitset集合 public BitSetIndex() {   } public BitSetIndexModel(String type) {  this.type = type;  map = new ConcurrentHashMap<String, Integer>();  list = new ArrayList<String>();  bsList = new ArrayList<BitSet>(); }  public String getType() {  return type; } public void setType(String type) {  this.type = type; } public Map<String, Integer> getMap() {  return map; } public void setMap(ConcurrentHashMap<String, Integer> map) {  this.map = map; } public List<String> getList() {  return list; } public void setList(List<String> list) {  this.list = list; } public List<BitSet> getBsList() {  return bsList; } public void setBsList(List<BitSet> bsList) {  this.bsList = bsList; }  public void createIndex(String str, int i) {  BitSet bitset = null;  //获取‘str'对应的bitset在bsList中的下标  Integer index = this.getMap().get(str);  if (index != null) {   bitset = this.getBsList().get(index);   if (bitset == null) {    bitset = new BitSet();    this.getBsList().add(index, bitset);   }   bitset.set(i, true);// 将str对应的位置为true,true可省略  } else {   bitset = new BitSet();   List<String> list = this.getList();   list.add(str);   index = list.size() - 1;   bitset.set(i, true);   this.getBsList().add(bitset);   this.getMap().put(str, index);  } }   public BitSet get(String str) {  BitSet bitset = null;  str = str.toLowerCase();  Integer index = this.getMap().get(str);  if (index != null) {   bitset = this.getBsList().get(index);  } else {   bitset = new BitSet();  }  return bitset; }  public BitSet and(String str, BitSet bitset) {  if (str != null) {   str = str.toLowerCase();   if (bitset != null) {    bitset.and(get(str));   } else {    bitset = new BitSet();    bitset.or(get(str));   }  }  return bitset; }  public BitSet or(String str, BitSet bitset) {  if (str != null) {   str = str.toLowerCase();   if (bitset != null) {    bitset.or(get(str));   } else {    bitset = new BitSet();    bitset.or(get(str));   }  }  return bitset; }  public static List<Integer> getRealIndexs(BitSet bitset) {  List<Integer> indexs = new ArrayList<Integer>();  if (bitset != null) {   int i = bitset.nextSetBit(0);   if (i != -1) {    indexs.add(i);    for (i = bitset.nextSetBit(i + 1); i >= 0; i = bitset.nextSetBit(i + 1)) {     int endOfRun = bitset.nextClearBit(i);     do {      indexs.add(i);     } while (++i < endOfRun);    }   }  }  return indexs; } }

为每一个user对象创建address,gender,age维度索引

public class UserIndexStore { private static final String ADDRESS = "address"; private static final String GENDER = "gender"; private static final String AGE = "age"; private BitSetIndexModel address; private BitSetIndexModel gender; private BitSetIndexModel age; private ConcurrentHashMap<Integer, User> userMap;//存储所有的user数据 public static final UserIndexStore INSTANCE = getInstance(); private UserIndexStore() {  init(); } public static UserIndexStore getInstance() {  return UserIndexStoreHolder.instance; } private static class UserIndexStoreHolder {  private static UserIndexStore instance = new UserIndexStore(); } private void init() {  this.address = new BitSetIndexModel(ADDRESS);  this.gender = new BitSetIndexModel(GENDER);  this.age = new BitSetIndexModel(AGE);  userMap = new ConcurrentHashMap<Integer, User>(); }  public void createIndex(List<User> users) {  if (users != null && users.size() > 0) {   for (int index = 0; index < users.size(); index++) {    User user = users.get(index);    getAddress().update(user.getAddress(), index);    getGender().update(user.getGender(), index);    getAge().update(user.getAge(), index);    this.userMap.put(index, user);   }  } } public BitSet query(String address, String gender, String age) {  BitSet bitset = null;  bitset = getAddress().and(address, bitset);  bitset = getGender().and(gender, bitset);  bitset = getAge().and(age, bitset);  return bitset; } public User findUser(Integer index) {  User user = this.userMap.get(index);  if (user != null) {   return user.clone();//可能会对user做修改操作,要保证内存原始数据不变  }  return null; } public BitSetIndexModel getAddress() {  return address; } public void setAddress(BitSetIndexModel address) {  this.address = address; } public BitSetIndexModel getGender() {  return gender; } public void setGender(BitSetIndexModel gender) {  this.gender = gender; } public BitSetIndexModel getAge() {  return age; } public void setAge(BitSetIndexModel age) {  this.age = age; }}

3.测试bitset

public class BitSetTest { public static void main(String[] args) {  List<User> users = buildData();  UserIndexStore.getInstance().createIndex(users);  ExecutorService executorService = Executors.newFixedThreadPool(20);  int num = 2000;  long begin1 = System.currentTimeMillis();  for (int i = 0; i < num; i++) {   Runnable syncRunnable = new Runnable() {    @Override    public void run() {     List<Integer> indexs = BitSetIndexModel.getRealIndexs(UserIndexStore.getInstance().query("北京", "girl", "18"));     for (Integer index : indexs) {      UserIndexStore.getInstance().findUser(index);     }    }   };   executorService.execute(syncRunnable);  }  executorService.shutdown();  while (true) {   try {    if (executorService.awaitTermination(1, TimeUnit.SECONDS)) {     System.out.println("单次查询时间为:" + (System.currentTimeMillis() - begin1) / num + "ms");     break;    }   } catch (InterruptedException e) {    e.printStackTrace();   }  } } private static List<User> buildData() {  String[] addresss = { "北京", "上海", "深圳" };  String[] ages = { "16", "17", "18" };  List<User> users = new ArrayList<>();  for (int i = 0; i < 200000; i++) {   User user = new User();   user.setName("name" + i);   int rand = ThreadLocalRandom.current().nextInt(3);   user.setAddress(addresss[ThreadLocalRandom.current().nextInt(3)]);   user.setGender((rand & 1) == 0 ? "girl" : "boy");   user.setAge(ages[ThreadLocalRandom.current().nextInt(3)]);   users.add(user);  }  return users; }}

测试结果(查询2w次):

数据量(users.size()) | 并发数 | 平均查询时间

---|---|---
20w | 10 | 1ms
50w | 20 | 3ms
100w| 50 | 9ms

测试机为thinkpad x240 i5 8g内存

4.总结

==优点==:

通过测试发现随着数据量的增大和并发数的提高,平均耗时并没有明显升高,并且响应时间都在10ms以内

==缺点==:

不适合数据量太大的情况,因为需要把数据全部加载进内存

不适合复杂查询

不适合对name,id等唯一值做查询

以上是“如何使用bitset实现毫秒级查询”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: 如何使用bitset实现毫秒级查询

本文链接: https://lsjlt.com/news/222194.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何使用bitset实现毫秒级查询
    这篇文章主要为大家展示了“如何使用bitset实现毫秒级查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用bitset实现毫秒级查询”这篇文章吧。bitset介绍看JDK中的解释简直一头...
    99+
    2023-05-31
    bitset
  • 1.3万亿条数据查询如何做到毫秒级响应?
    作为中国最大的知识共享平台,我们目前拥有 2.2 亿注册用户,3000 万个问题,网站答案超过 1.3 亿。 随着用户群的增长,我们的应用程序的数据大小无法实现。我们的 Moneta 应用程序中存储了...
    99+
    2024-04-02
  • 如何使用php Swoole实现毫秒定时计划任务
    这篇文章主要介绍了如何使用php Swoole实现毫秒定时计划任务,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。项目开发中,如果有定时任务的业务要求,我们会使用linux的c...
    99+
    2023-06-29
  • 用Python实现淘宝京东毫秒级秒杀,看谁还能抢过我
    你还在为各种活动秒杀 抢不过别人而烦恼吗 今天就来教你如何用Python来实现淘宝京东毫秒级的抢购,用Python来告诉你,秒杀就是这么简单!!! 妈妈再也不要担心我抢不到限时秒杀特价商品啦!!! ...
    99+
    2023-09-25
    python pycharm 职场和发展 程序人生 学习
  • mysql上亿数据秒级查询怎么实现
    要实现MySQL上亿数据的秒级查询,需要考虑以下几个方面:1. 数据分库分表:将数据分散存储在多个数据库和表中,以减少单个数据库或表...
    99+
    2023-10-27
    mysql
  • 使用MySQL如何实现分页查询
    目录一、分页1. 什么是分页2. 真分页3. 假分页4. 缓存层二、MySQL实现分页1. LIMIT用法2. 分页公式8种MySQL分页方法总结方法1: 直接使用数据库提供的SQL...
    99+
    2024-04-02
  • 使用mybatis如何实现查询缓存
    这篇文章将为大家详细讲解有关使用mybatis如何实现查询缓存,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1 缓存的意义将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上...
    99+
    2023-05-31
    mybatis 查询缓存
  • 如何使用Redis实现秒杀
    如何使用Redis实现秒杀?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。导语:秒杀想必大家都了解,在短时间内请求访问会激增,同...
    99+
    2024-04-02
  • Kylin的查询性能是如何达到秒级响应的
    Kylin实现秒级响应的关键在于其采用了多维数据分析引擎和预计算技术。具体来说,Kylin通过以下方式实现了高性能的查询响应: ...
    99+
    2024-03-07
    Kylin
  • 如何使用Bootstrap4 + Vue2实现分页查询
    小编给大家分享一下如何使用Bootstrap4 + Vue2实现分页查询,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!写在前面工...
    99+
    2024-04-02
  • MyBatis如何使用PageHelper实现分页查询
    目录使用PageHelper实现分页查询1、创建数据表2、创建项目2.1 创建实体类(Entity层)2.2 数据库映射层(Mapper层)3、运行测试MyBatis PageHel...
    99+
    2024-04-02
  • MybatisPlus使用queryWrapper如何实现复杂查询
    目录使用queryWrapper实现复杂查询自定义的queryWrapper实现查询声明提要核心代码使用queryWrapper实现复杂查询 // mp实现负责查询操作 ...
    99+
    2024-04-02
  • MySQL 普通查询、流式查询、游标查询以及使用 mybatis 如何实现
    MySQL 普通查询、流式查询、游标查询以及使用 mybatis 如何实现 MySQL 普通查询、流式查询、游标查询以及使用 mybatis 如何实现普通查询流式查询游标查询mybatis 如...
    99+
    2023-09-28
    mybatis java mysql
  • 如何使用SQL语句实现表的查询
    这篇文章主要介绍“如何使用SQL语句实现查询”,在日常操作中,相信很多人在如何使用SQL语句实现查询问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用SQL语句实现查询”...
    99+
    2024-04-02
  • 如何使用PHP实现数组模糊查询
    在PHP中,我们经常需要对数组进行搜索和过滤操作,其中,模糊查询是一个常见的需求。本文将介绍如何使用PHP实现数组模糊查询,以及一些常见应用场景。一、模糊查询数组key在PHP中,可以使用foreach和array_search两种方式进行...
    99+
    2023-05-14
  • myBatis如何实现查询
    这篇文章主要为大家展示了“myBatis如何实现查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“myBatis如何实现查询”这篇文章吧。把查询的字段,查询的条...
    99+
    2024-04-02
  • python如何实现查询
    这篇文章主要为大家展示了“python如何实现查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何实现查询”这篇文章吧。查询排序和查询都是好基友,长的数据结构里面(字典,列表)里面...
    99+
    2023-06-16
  • 如何实现OJB查询
    这篇文章给大家分享的是有关如何实现OJB查询的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。OJB查询联接:在path expressions中(relationship.attribute)声明的联接在crite...
    99+
    2023-06-03
  • 如何使用Redis实现秒杀功能
    这篇文章主要介绍如何使用Redis实现秒杀功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 怎样预防数据库超售现象设置数据库事务的隔离级别为Serializable(不可用)Serializable就是让数据库...
    99+
    2023-06-14
  • 如何使用mongoose实现多集合关联查询
    这篇文章主要介绍了如何使用mongoose实现多集合关联查询,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在使用node开发后端项目的时候,通常会选择mongodb作为数据库...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作