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编码。

  • 相关阅读:
    搭建家庭无线Adhoc网络
    IPv4到IPv6的过渡技术
    IPV6的安全性
    IPv6技术简要解析
    安全删除和恢复文件的脚本
    什么是 WPS(WiFi Protected Setup)
    华为:IPv6过渡技术中的探索
    IPV6地址设置及使用方法
    部分IIS日志参数名称解释
    《隐秘的角落》
  • 原文地址:https://www.cnblogs.com/23lalala/p/4201153.html
Copyright © 2011-2022 走看看