zoukankan      html  css  js  c++  java
  • 日期的压缩存储daybits

    问题:

    存储一个日期的序列,例如保存用户一年的登录时间序列,20140201,20130102这样两个日期,如果用INT那么需要八个字节,用STRING就更多了。

    解决:

    通过bit来存储一天,具体的组织形式是这样的

    struct daybits {

        Year[] before_years;

        Year[] after_years;

    }

    struct Year {

        Quarter q1;

        Quarter q2;

        Quarter q3;

        Quarter q4;

    }

    struct Quarter {

        byte[] bytes

    }

    日期压缩过程 

    daybits中有若干个年,以2013做为轴分别存储在before和after years数组里。每个年有四个季度,每个季度中有个byte数组,数组中的每个字节代表8天,bytes[i] 代表这个季度的第i*8 - (i+1) * 8天,其实就是Java BitSet不用INT存储,用BYTE存储。还有一点和JAVA的BitSet不同的是,Quarter中的byte数组,使用了延迟加载,当在某一个季度登录过,这个季度才分配存储空间,并且,分配的空间也不是每次把一个季度中的90天(假设一个月30天)全都分配了(最多也就是分配12个字节可以表示96天,够一个季度的天数了),而是最大需要多少天分配多少字节,如果这个季度之后的天又需要存储,那么重新分配空间再memcpy。通过这种分季度,节约了很大一部分的存储。如果一个季度登录过三天应该就比用INT存储登录时间要高效,如果是只登录了一天,而且是在季度的最后一天,那就亏了。

    例子


    存储20140105

    2014年存储在after_years[1]中

    1月存储year的q1中

    计算2014年1月1日的时间戳,计算2014年1月5日的时间戳,相减除以3600*24秒得到是1月的第五天

    存储在byte[0],且值为二进制的00010000,代表第五天

    反解的时候通过月的第N天解出是几月几日有点麻烦,如果有Java Calendar处理这个还比较简单,不过这个东西可以提前计算好

    daybits的ToString

    用"#",区分了上半区和下半区,用";"区分了每年,用","区分了每个季度,每个季度的bytes数组用base64编码。

  • 相关阅读:
    在线自动创建springboot工程
    java线程自带队列的使用以及线程阻塞
    如何分析java内存泄漏问题
    java接口入参模板化,适用于企业化服务远程调度模板化的场景,接口入参实现高度可配置化
    打造springboot高性能服务器(spring reactor的使用)
    docker 5 docker-阿里云加速配置
    docker 4 docker的三要素
    docker 3 docker安装
    docker 2 docker介绍
    docker 1 为什么要使用docker
  • 原文地址:https://www.cnblogs.com/23lalala/p/4201153.html
Copyright © 2011-2022 走看看