精华内容
下载资源
问答
  • SQL中的五种数据类型

    千次阅读 2017-09-18 21:58:17
    SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型简要描述一下SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型字符型VARCHAR 和 CHARVARCHAR型和CHAR型数据的这个差别是细微的,但是非常...

    SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型

    简要描述一下SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型

    字符型

    VARCHAR 和 CHAR

    VARCHAR型和CHAR型数据的这个差别是细微的,但是非常重要。他们都是用来储存字符串长度小于255的字符。

    假如你向一个长度为四十个字符的VARCHAR型字段中输入数据Bill Gates。当你以后从这个字段中取出此数据时,你取出的数据其长度为十个字符——字符串Bill Gates的长度。 现在假如你把字符串输入一个长度为四十个字符的CHAR型字段中,那么当你取出数据时,所取出的数据长度将是四十个字符。字符串的后面会被附加多余的空格。

    当你建立自己的站点时,你会发现使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段时,你不需要为剪掉你数据中多余的空格而操心。

    VARCHAR型字段的另一个突出的好处是它可以比CHAR型字段占用更少的内存和硬盘空间。当你的数据库很大时,这种内存和磁盘空间的节省会变得非常重要

    文本型

    TEXT

    使用文本型数据,你可以存放超过二十亿个字符的字符串。当你需要存储大串的字符时,应该使用文本型数据。

    注意文本型数据没有长度,而上一节中所讲的字符型数据是有长度的。一个文本型字段中的数据通常要么为空,要么很大。

    当你从HTML form的多行文本编辑框(TEXTAREA)中收集数据时,你应该把收集的信息存储于文本型字段中。但是,无论何时,只要你能避免使用文本型字段,你就应该不适用它。文本型字段既大且慢,滥用文本型字段会使服务器速度变慢。文本型字段还会吃掉大量的磁盘空间。

    一旦你向文本型字段中输入了任何数据(甚至是空值),就会有2K的空间被自动分配给该数据。除非删除该记录,否则你无法收回这部分存储空间。

    数值型

    SQL支持许多种不同的数值型数据。你可以存储整数 INT 、小数 NUMERIC、和钱数 MONEY。

    INT VS SMALLINT VS TINYINT
    他们的区别只是字符长度: INT型数据的表数范围是从-2,147,483,647到2,147,483,647的整数SMALLINT 型数据可以存储从-32768到32768的整数TINYINT 型的字段只能存储从0到255的整数,不能用来储存负数
    通常,为了节省空间,应该尽可能的使用最小的整型数据。一个TINYINT型数据只占用一个字节;一个INT型数据占用四个字节。这看起来似乎差别不大,但是在比较大的表中,字节数的增长是很快的。另一方面,一旦你已经创建了一个字段,要修改它是很困难的。因此,为安全起见,你应该预测以下,一个字段所需要存储的数值最大有可能是多大,然后选择适当的数据类型。

    MUNERIC

    为了能对字段所存放的数据有更多的控制,你可以使用NUMERIC型数据来同时表示一个数的整数部分和小数部分。NUMERIC型数据使你能表示非常大的数——比INT型数据要大得多。一个NUMERIC型字段可以存储从-1038到1038范围内的数。NUMERIC型数据还使你能表示有小数部分的数。例如,你可以在NUMERIC型字段中存储小数3.14。

    当定义一个NUMERIC型字段时,你需要同时指定整数部分的大小和小数部分的大小。如:MUNERIC(23,0)

    一个 NUMERIC型数据的整数部分最大只能有28位,小数部分的位数必须小于或等于整数部分的位数,小数部分可以是零。

    MONEY VS SMALLMONEY

    你可以使用 INT型或NUMERIC型数据来存储钱数。但是,专门有另外两种数据类型用于此目的。如果你希望你的网点能挣很多钱,你可以使用MONEY型数据。如果你的野心不大,你可以使用SMALLMONEY型数据。MONEY型数据可以存储从-922,337,203,685,477.5808到922,337,203,685,477.5807的钱数。如果你需要存储比这还大的金额,你可以使用NUMERIC型数据。

    SMALLMONEY型数据只能存储从-214,748.3648到214,748.3647 的钱数。同样,如果可以的话,你应该用SMALLMONEY型来代替MONEY型数据,以节省空间。

    逻辑型

    BIT

    如果你使用复选框( CHECKBOX)从网页中搜集信息,你可以把此信息存储在BIT型字段中。BIT型字段只能取两个值:0或1。

    当心,在你创建好一个表之后,你不能向表中添加 BIT型字段。如果你打算在一个表中包含BIT型字段,你必须在创建表时完成。

    日期型

    DATETIME VS SMALLDATETIME

    一个 DATETIME型的字段可以存储的日期范围是从1753年1月1日第一毫秒到9999年12月31日最后一毫秒。

    如果你不需要覆盖这么大范围的日期和时间,你可以使用SMALLDATETIME型数据。它与DATETIME型数据同样使用,只不过它能表示的日期和时间范围比DATETIME型数据小,而且不如DATETIME型数据精确。一个SMALLDATETIME型的字段能够存储从1900年1月1日到2079年6月6日的日期,它只能精确到秒。

    DATETIME型字段在你输入日期和时间之前并不包含实际的数据

    原文转自:http://www.cnblogs.com/shenliang123/archive/2012/04/07/2435908.html

    展开全文
  • Redis的9种数据类型

    千次阅读 2018-11-01 09:53:57
    在具体描述这几种数据类型之前,我们先通过一张图了解下 Redis 内部内存管理中是如何描述这些不同数据类型的: 首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示...

    在具体描述这几种数据类型之前,我们先通过一张图了解下 Redis 内部内存管理中是如何描述这些不同数据类型的:

    首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。

    这需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的,该功能会在后面具体描述。通过上图我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用,我们随后会具体讨论。

    redis支持丰富的数据类型,不同的场景使用合适的数据类型可以有效的优化内存数据的存放空间:

    1. string:最基本的数据类型,二进制安全的字符串,最大512M。
    2. list:按照添加顺序保持顺序的字符串列表。
    3. set:无序的字符串集合,不存在重复的元素
    4. sorted set:已排序的字符串集合。
    5. hash:key-value对的一种集合。
    6. bitmap:更细化的一种操作,以bit为单位。
    7. hyperloglog:基于概率的数据结构。 # 2.8.9新增
    8. Geo:地理位置信息储存起来, 并对这些信息进行操作   # 3.2新增
    9. 流(Stream)# 5.0新增

    String 字符串

    常用命令:

    setnx,set,get,decr,incr,mget 等。

    应用场景:

    字符串是最常用的数据类型,他能够存储任何类型的字符串,当然也包括二进制、JSON化的对象、甚至是Base64编码之后的图片。在Redis中一个字符串最大的容量为512MB,可以说是无所不能了。redis的key和string类型value限制均为512MB。

    • 缓存,热点数据
    • 分布式session
    • 分布式锁
    • INCR计数器
    • 文章的阅读量,微博点赞数,允许一定的延迟,先写入 Redis 再定时同步到数据库
    • 全局ID
    •      INT 类型,INCRBY,利用原子性
    • INCR 限流
    •      以访问者的 IP 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false。
    • setbit 位操作

    内部编码:

    •     int:8 个字节的长整型(long,2^63-1)
    •     embstr:小于等于44个字节的字符串,embstr格式的SDS(Simple Dynamic String)
    •     raw:SDS大于 44 个字节的字符串

    通过下图可以直观感受一下字符串类型和哈希类型的区别:

    redis 为什么要自己写一个SDS的数据类型,主要是为了解决C语言 char[] 的四个问题

    • 字符数组必须先给目标变量分配足够的空间,否则可能会溢出
    • 查询字符数组长度 时间复杂度O(n)
    • 长度变化,需要重新分配内存
    • 通过从字符串开始到结尾碰到的第一个\0来标记字符串的结束,因此不能保存图片、音频、视频、压缩文件等二进制(bytes)保存的内容,二进制不安全

    redis SDS

    • 不用担心内存溢出问题,如果需要会对 SDS 进行扩容
    • 因为定义了 len 属性,查询数组长度时间复杂度O(1) 固定长度
    • 空间预分配,惰性空间释放
    • 根据长度 len来判断是结束,而不是 \0

     

    Hash 哈希表

    常用命令:

    hget,hsetnx,hset,hvals,hgetall,hmset,hmget 等。

    redis> HSET phone myphone nokia-1110
    (integer) 1
    
    redis> HEXISTS phone myphone
    (integer) 1
    
    redis> HSET people jack "Jack Sparrow"
    (integer) 1
    
    redis> HSET people gump "Forrest Gump"
    (integer) 1
    
    redis> HGETALL people
    1) "jack"          # 域
    2) "Jack Sparrow"  # 值
    3) "gump"
    4) "Forrest Gump"

    应用场景:

    我们简单举个实例来描述下 Hash 的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:用户 ID 为查找的 key,存储的 value 用户对象包含姓名,年龄,生日等信息,如果用普通的 key/value 结构来存储,主要有以下2种存储方式:

    第一种方式将用户 ID 作为查找 key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。

    第二种方法是这个用户信息对象有多少成员就存成多少个 key-value 对儿,用用户 ID +对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户 ID 为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。

    那么 Redis 提供的 Hash 很好的解决了这个问题,Redis 的 Hash 实际是内部存储的 Value 为一个 HashMap,并提供了直接存取这个 Map 成员的接口,如下图:

    也就是说,Key 仍然是用户 ID,value 是一个 Map,这个 Map 的 key 是成员的属性名,value 是属性值,这样对数据的修改和存取都可以直接通过其内部 Map 的 Key(Redis 里称内部 Map 的 key 为 field),也就是通过 key(用户 ID) + field(属性标签)就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。这里同时需要注意,Redis 提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部 Map 的成员很多,那么涉及到遍历整个内部 Map 的操作,由于 Redis 单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。

     购物车

    内部编码:

    •     ziplist(压缩列表):当哈希类型中元素个数小于 hash-max-ziplist-entries 配置(默认 512 个),同时所有值都小于 hash-max-ziplist-value 配置(默认 64 字节)时,Redis 会使用 ziplist 作为哈希的内部实现。
    •     hashtable(哈希表):当上述条件不满足时,Redis 则会采用 hashtable 作为哈希的内部实现。

    下面我们通过以下命令来演示一下 ziplist 和 hashtable 这两种内部编码。
    当 field 个数比较少并且 value 也不是很大时候 Redis 哈希类型的内部编码为 ziplist:

    当 value 中的字节数大于 64 字节时(可以通过 hash-max-ziplist-value 设置),内部编码会由 ziplist 变成 hashtable。

    当 field 个数超过 512(可以通过 hash-max-ziplist-entries 参数设置),内部编码也会由 ziplist 变成 hashtable

    List 列表

    常用命令:

    lpush,rpush,lpop,rpop,lrange等。

    127.0.0.1:6379> lpush list one   # 将一个值或者多个值,插入到列表的头部(左)(integer) 1
    127.0.0.1:6379> lpush list two
    (integer) 2
    127.0.0.1:6379> lpush list three 
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1   # 查看全部元素
    1) "three"
    2) "two"
    3) "one"
    127.0.0.1:6379> lrange list 0 1    # 通过区间获取值
    1) "three"
    2) "two"
    127.0.0.1:6379> rpush list right   # 将一个值或者多个值,插入到列表的尾部(右)(integer) 4
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "right"
    127.0.0.1:6379>

    列表(list)用来存储多个有序的字符串,每个字符串称为元素;一个列表可以存储2^32-1个元素。Redis中的列表支持两端插入和弹出,并可以获得指定位置(或范围)的元素,可以充当数组、队列、栈等

    应用场景

    比如 twitter 的关注列表,粉丝列表等都可以用 Redis 的 list 结构来实现,可以利用lrange命令,做基于Redis的分页功能,性能极佳,用户体验好。

    消息队列

    列表类型可以使用 rpush 实现先进先出的功能,同时又可以使用 lpop 轻松的弹出(查询并删除)第一个元素,所以列表类型可以用来实现消息队列

    发红包的场景

    在发红包的场景中,假设发一个10元,10个红包,需要保证抢红包的人不会多抢到,也不会少抢到

    下面我们通过下图来看一下 Redis 中列表类型的插入和弹出操作:

    下面我们看一下 Redis 中列表类型的获取与删除操作:

    Redis 列表类型的特点如下:

    •     列表中所有的元素都是有序的,所以它们是可以通过索引获取的lindex 命令。并且在 Redis 中列表类型的索引是从 0 开始的。
    •     列表中的元素是可以重复的,也就是说在 Redis 列表类型中,可以保存同名元素

    内部编码:

    •     ziplist(压缩列表):当列表中元素个数小于 512(默认)个,并且列表中每个元素的值都小于 64(默认)个字节时,Redis 会选择用 ziplist 来作为列表的内部实现以减少内存的使用。当然上述默认值也可以通过相关参数修改:list-max-ziplist-entried(元素个数)、list-max-ziplist-value(元素值)。
    •     linkedlist(链表):当列表类型无法满足 ziplist 条件时,Redis 会选择用 linkedlist 作为列表的内部实现。

    Set 集合

    常用命令:

    sadd,spop,smembers,sunion,scard,sscan,sismember等。

    # 初始化
    sadd poker T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 TJ TQ TK X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 XJ XQ XK M1 M2 M3 M4 M5 M6 M7 M8 M9 M10 MJ MQ MK F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 FJ FQ FK XW DW
    
    # 数量
    scard poker
    
    # 复用扑克牌
    sunionstore pokernew poker
    
    # 成员
    smembers poker
    
    # 是否包含
    sismember poker T1
    
    # 随机读取
    spop poker
    
    # 设置
    sadd user1tag tagID1 tagID2 tagID3
    sadd user2tag tagID2 tagID3
    sadd user3tag tagID2 tagID4 tagID5
    
    # 获取共同拥有的tag(交集)
    sinter user1tag user2tag user3tag
    
    # 获取拥有的所有tag(并集)
    sunion user1tag user2tag user3tag
    
    # 获取两个之间的区别(差集)
    sdiff user2tag user3tag

    应用场景:

    Redis set 对外提供的功能与 list 类似是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。

    • 1知乎点赞数

    • 2京东的商品筛选

    127.0.0.1:6379> sadd brand:apple iPhone11
    (integer) 1
    127.0.0.1:6379> sadd brand:ios iPhone11
    (integer) 1
    127.0.0.1:6379> sadd screensize:6.0-6.24 iPhone11
    (integer) 1
    127.0.0.1:6379> sadd memorysize:256GB iPhone11
    (integer) 1
    127.0.0.1:6379> sinter brand:apple brand:ios screensize:6.0-6.24 memorysize:256GB
    1) "iPhone11"
    

    筛选商品,苹果,IOS,屏幕6.0-6.24,内存大小256G

    sinter brand:apple brand:ios screensize:6.0-6.24 memorysize:256GB

    • 3.存储社交关系

    用户(编号user001)关注

    sadd focus:user001 user003

    sadd focus:user002 user003 user004

    相互关注

    sadd focus:user001 user002

    sadd focus:user002 user001

    #判断用户2是否关注了用户1
    127.0.0.1:6379> SISMEMBER focus:user002 user001
    (integer) 1
    

    我关注得到人也关注了他(共同关注) 

    #获取关注的交集
    127.0.0.1:6379> sinter focus:user001 focus:user002
    1) "user003"
    

    可能认识的人

    #将所有的人存放到allusers集合
    127.0.0.1:6379> SUNIONSTORE alluser:user001 focus:user001 focus:user002
    (integer) 4
    127.0.0.1:6379> SDIFF alluser:user001 focus:user001
    1) "user004"
    2) "user001"
    #剔除掉自己
    127.0.0.1:6379> SREM alluser:user001 user001
    (integer) 1
    127.0.0.1:6379> SDIFF alluser:user001 focus:user001
    1) "user004"
    

    实现方式:

    set 的内部实现是一个 value 永远为 null 的 HashMap,实际就是通过计算 hash 的方式来快速排重的,这也是 set 能提供判断一个成员是否在集合内的原因。

    Redis 中的集合类型,也就是 set。在 Redis 中 set 也是可以保存多个字符串的,经常有人会分不清 list 与 set,下面我们重点介绍一下它们之间的不同:

    •     set 中的元素是不可以重复的,而 list 是可以保存重复元素的
    •     set 中的元素是无序的,而 list 中的元素是有序的
    •     set 中的元素不能通过索引下标获取元素,而 list 中的元素则可以通过索引下标获取元素。
    •     除此之外 set 还支持更高级的功能,例如多个 set 取交集、并集、差集等

    为什么 Redis 要提供 sinterstore、sunionstore、sdiffstore 命令来将集合的交集、并集、差集的结果保存起来呢?这是因为 Redis 在进行上述比较时,会比较耗费时间,所以为了提高性能可以将交集、并集、差集的结果提前保存起来,这样在需要使用时,可以直接通过 smembers 命令获取。

    内部编码

    •     intset(整数集合):当集合中的元素都是整数,并且集合中的元素个数小于 512 个时,Redis 会选用 intset 作为底层内部实现。
    •     hashtable(哈希表):当上述条件不满足时,Redis 会采用 hashtable 作为底层实现。

    备注:我们可以通过 set-max-intset-entries 参数来设置上述中的默认参数。

    Sorted set 有序集合

    常用命令:

    zadd,zrange,zrem,zcard,zscore,zcount,zlexcount等

    redis> ZRANGE salary 0 -1 WITHSCORES    # 测试数据
    1) "tom"
    2) "2000"
    3) "peter"
    4) "3500"
    5) "jack"
    6) "5000"
    
    redis> ZSCORE salary peter              # 注意返回值是字符串
    "3500"
    
    redis> ZCOUNT salary 2000 5000          # 计算薪水在 2000-5000 之间的人数
    (integer) 3
    
    # rank:key 100: 分数 u1: ID
    # 初始化 时间复杂度: O(log(N))
    zadd rank 100 u1
    zadd rank 200 u2
    zadd rank 300 u3
    zadd rank 400 u4
    zadd rank 500 u5
    
    # 数量
    zcard rank
    
    # 内容(正序、倒序)时间复杂度: O(log(N)+M)
    zrange rank 0 -1
    zrange rank 0 -1 withscores
    
    zrevrange rank 0 -1 withscores
    zrevrange rank 0 -2 withscores
    zrevrange rank 0 -1
    
    # 获取用户分数(不存在返回空) 时间复杂度: O(1)
    zscore rank u1
    
    # 修改分数
    zadd rank 800 u3
    
    # 修改分数(累加:新增或减少,返回修改后的分数)
    zincrby rank 100 u3
    zincrby rank -100 u3
    
    # 查询分数范围内容(正序、倒序)
    zrangebyscore rank (200 800 withscores
    zrevrangebyscore rank (200 800 withscores
    
    # 移除元素
    zrem rank u3
    下面先看一下列表、集合、有序集合三种数据类型之间的区别:


    内部编码:

    • ziplist(压缩列表):当有序集合的元素个数小于 128 个(默认设置),同时每个元素的值都小于 64 字节(默认设置),Redis 会采用 ziplist 作为有序集合的内部实现。
    • skiplist(跳跃表):当上述条件不满足时,Redis 会采用 skiplist 作为内部编码。

    备注:上述中的默认值,也可以通过以下参数设置:zset-max-ziplist-entries 和 zset-max-ziplist-value。

    应用场景

    Redis sorted set 的使用场景与 set 类似,区别是 set 不是自动有序的,而 sorted set 可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择 sorted set 数据结构,比如 twitter 的 public timeline 可以以发表时间作为 score 来存储,这样获取时就是自动按时间排好序的。点击数做出排行榜。

    1.商品的评价标签,可以记录商品的标签,统计标签次数,增加标签次数,按标签的分值进行排序

    #添加商品(编号i5001)的标签tag和对应标签的评价次数
    127.0.0.1:6379> zadd goods_tag:i5001 442 tag1 265 tag2 264 tag3
    (integer) 3
    #不带分数
    127.0.0.1:6379> zrange goods_tag:i5001 0 -1
    1) "tag3"
    2) "tag2"
    3) "tag1"
    #带分数
    127.0.0.1:6379> zrange goods_tag:i5001 0 -1 withscores
    1) "tag3"
    2) "264"
    3) "tag2"
    4) "265"
    5) "tag1"
    6) "442"
    

     2.百度搜索热点

    #维护2020年1月21号的热点新闻
    127.0.0.1:6379> zadd hotspot:20200121 520 pot1 263 pot2 244 pot3
    (integer) 3
    127.0.0.1:6379> zrange hotspot:20200121 0 -1 withscores
    1) "pot3"
    2) "244"
    3) "pot2"
    4) "263"
    5) "pot1"
    6) "520"
    #增加点击次数
    127.0.0.1:6379> ZINCRBY hotspot 1 pot1
    "521"
    

    3.反spam系统

    作为一个电商网站被各种spam攻击是少不免(垃圾评论、发布垃圾商品、广告、刷自家商品排名等)针对这些spam制定一系列anti-spam规则,其中有些规则可以利用redis做实时分析
    譬如:1分钟评论不得超过2次、5分钟评论少于5次等

    #获取5秒内操作记录
    $res = $redis->zRangeByScore('user:1000:comment', time() - 5, time());
    #判断5秒内不能评论
    if (!$res) {
        $redis->zAdd('user:1000:comment', time(), '评论内容');
    } else {
        echo '5秒之内不能评论';
    }
     
    #5秒内评论不得超过2次
    if($redis->zRangeByScore('user:1000:comment',time()-5 ,time())==1)
    echo '5秒之内不能评论2次';
     
    #5秒内评论不得少于2次
    if(count($redis->zRangeByScore('user:1000:comment',time()-5 ,time()))<2)
    echo '5秒之内不能评论2次';

    BitMap 位图

    在应用场景中,有一些数据只有两个属性,比如是否是学生,是否是党员等等,对于这些数据,最节约内存的方式就是用bit去记录,以是否是学生为例,1代表是学生,0代表不是学生。那么1000110就代表7个人中3个是学生,这就是BitMaps的存储需求。Bitmaps是一个可以对位进行操作的字符串,我们可以把Bitmaps想象成是一串二进制数字,每个位置只存储0和1。下标是Bitmaps的偏移量。BitMap 就是通过一个 bit 位来表示某个元素对应的值或者状态, 其中的 key 就是对应元素本身,实际上底层也是通过对字符串的操作来实现。Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令,但是并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩展。

    使用场景一:用户签到

    很多网站都提供了签到功能(这里不考虑数据落地事宜),并且需要展示最近一个月的签到情况
    <?php
    $redis = new Redis();
    $redis->connect('127.0.0.1');
    
    //用户uid
    $uid = 1;
    
    //记录有uid的key
    $cacheKey = sprintf("sign_%d", $uid);
    
    //开始有签到功能的日期
    $startDate = '2017-01-01';
    
    //今天的日期
    $todayDate = '2017-01-21';
    
    //计算offset
    $startTime = strtotime($startDate);
    $todayTime = strtotime($todayDate);
    $offset = floor(($todayTime - $startTime) / 86400);
    
    echo "今天是第{$offset}天" . PHP_EOL;
    
    //签到
    //一年一个用户会占用多少空间呢?大约365/8=45.625个字节,好小,有木有被惊呆?
    $redis->setBit($cacheKey, $offset, 1);
    
    //查询签到情况
    $bitStatus = $redis->getBit($cacheKey, $offset);
    echo 1 == $bitStatus ? '今天已经签到啦' : '还没有签到呢';
    echo PHP_EOL;
    
    //计算总签到次数
    echo $redis->bitCount($cacheKey) . PHP_EOL;
    
    /**
     * 计算某段时间内的签到次数
     * 很不幸啊,bitCount虽然提供了start和end参数,但是这个说的是字符串的位置,而不是对应"位"的位置
     * 幸运的是我们可以通过get命令将value取出来,自己解析。并且这个value不会太大,上面计算过一年一个用户只需要45个字节
     * 给我们的网站定一个小目标,运行30年,那么一共需要1.31KB(就问你屌不屌?)
     */
    //这是个错误的计算方式
    echo $redis->bitCount($cacheKey, 0, 20) . PHP_EOL;
    

    使用场景二:统计活跃用户

    使用时间作为cacheKey,然后用户ID为offset,如果当日活跃过就设置为1
    那么我该如果计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只有有一天在线就称为活跃),有请下一个redis的命令
    命令 BITOP operation destkey key [key ...]
    说明:对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
    说明:BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数

    bitop and destKey key1 key2....  //交
    bitop or destKey key1 key2....   //并
    bitop not destKey key1 key2....  //非
    bitop xor destKey key1 key2....  //异或
    <?php
    //日期对应的活跃用户
    $data = array(
        '2017-01-10' => array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),

        '2017-01-11' => array(1, 2, 3, 4, 5, 6, 7, 8),

        '2017-01-12' => array(1, 2, 3, 4, 5, 6),

        '2017-01-13' => array(1, 2, 3, 4),
        '2017-01-14' => array(1, 2)

    );
    //批量设置活跃状态

    foreach ($data as $date => $uids) {
        $cacheKey = sprintf("stat_%s", $date);
        foreach ($uids as $uid) {
            $redis->setBit($cacheKey, $uid, 1);
        }
    }
    $redis->bitOp('AND', 'stat', 'stat_2017-01-10', 'stat_2017-01-11', 'stat_2017-01-12') . PHP_EOL;
    //总活跃用户:6

    echo "总活跃用户:" . $redis->bitCount('stat') . PHP_EOL;
    
    $redis->bitOp('AND', 'stat1', 'stat_2017-01-10', 'stat_2017-01-11', 'stat_2017-01-14') . PHP_EOL;
    

    //总活跃用户:2

    echo "总活跃用户:" . $redis->bitCount('stat1') . PHP_EOL;
    
    $redis->bitOp('AND', 'stat2', 'stat_2017-01-10', 'stat_2017-01-11') . PHP_EOL; //总活跃用户:8

    echo "总活跃用户:" . $redis->bitCount('stat2') . PHP_EOL;

    使用场景三:用户在线状态

    前段时间开发一个项目,对方给我提供了一个查询当前用户是否在线的接口。不了解对方是怎么做的,自己考虑了一下,使用bitmap是一个节约空间效率又高的一种方法,只需要一个key,然后用户ID为offset,如果在线就设置为1,不在线就设置为0,和上面的场景一样,5000W用户只需要6MB的空间。

    <?php
    //批量设置在线状态
    $uids = range(1, 500000);
    foreach ($uids as $uid) {
        $redis->setBit('online', $uid, $uid % 2);
    }
    //一个一个获取状态
    $uids = range(1, 500000);
    $startTime = microtime(true);
    foreach ($uids as $uid) {
        echo $redis->getBit('online', $uid) . PHP_EOL;
    }
    $endTime = microtime(true);
    
    //在我的电脑上,获取50W个用户的状态需要25秒

    echo "total:" . ($endTime - $startTime) . "s";

    内部编码

    这个就是Redis实现的BloomFilter,BloomFilter非常简单,如下图所示,假设已经有3个元素a、b和c,分别通过3个hash算法h1()、h2()和h2()计算然后对一个bit进行赋值,接下来假设需要判断d是否已经存在,那么也需要使用3个hash算法h1()、h2()和h2()对d进行计算,然后得到3个bit的值,恰好这3个bit的值为1,这就能够说明:d可能存在集合中。再判断e,由于h1(e)算出来的bit之前的值是0,那么说明:e一定不存在集合中:

    需要说明的是,bitmap并不是一种真实的数据结构,它本质上是String数据结构,只不过操作的粒度变成了位,即bit。因为String类型最大长度为512MB,所以bitmap最多可以存储2^32个bit。 

    HyperLogLog 基数统计

    HyperLogLog算法时一种非常巧妙的近似统计大量去重元素数量的算法,它内部维护了16384个桶来记录各自桶的元素数量,当一个元素过来,它会散列到其中一个桶。当元素到来时,通过 hash 算法将这个元素分派到其中的一个小集合存储,同样的元素总是会散列到同样的小集合。这样总的计数就是所有小集合大小的总和。使用这种方式精确计数除了可以增加元素外,还可以减少元素


    一个HyperLogLog实际占用的空间大约是 13684 * 6bit / 8 = 12k 字节。但是在计数比较小的时候,大多数桶的计数值都是零。如果 12k 字节里面太多的字节都是零,那么这个空间是可以适当节约一下的。Redis 在计数值比较小的情况下采用了稀疏存储,稀疏存储的空间占用远远小于 12k 字节。相对于稀疏存储的就是密集存储,密集存储会恒定占用 12k 字节。

    内部编码

    HyperLogLog 整体的内部结构就是 HLL 对象头 加上 16384 个桶的计数值位图。它在 Redis 的内部结构表现就是一个字符串位图。你可以把 HyperLogLog 对象当成普通的字符串来进行处理。

    应用场景

    Redis 的基数统计,这个结构可以非常省内存的去统计各种计数,比如注册 IP 数、每日访问 IP 数、页面实时UV)、在线用户数等。但是它也有局限性,就是只能统计数量,而没办法去知道具体的内容是什么。当然用集合也可以解决这个问题。但是一个大型的网站,每天 IP 比如有 100 万,粗算一个 IP 消耗 15 字节,那么 100 万个 IP 就是 15M。而 HyperLogLog 在 Redis 中每个键占用的内容都是 12K,理论存储近似接近 2^64 个值,不管存储的内容是什么,它一个基于基数估算的算法,只能比较准确的估算出基数,可以使用少量固定的内存去存储并识别集合中的唯一元素。而且这个估算的基数并不一定准确,是一个带有 0.81% 标准错误的近似值。

    HyperLogLog 主要的应用场景就是进行基数统计。这个问题的应用场景其实是十分广泛的。例如:对于 Google 主页面而言,同一个账户可能会访问 Google 主页面多次。于是,在诸多的访问流水中,如何计算出 Google 主页面每天被多少个不同的账户访问过就是一个重要的问题。那么对于 Google 这种访问量巨大的网页而言,其实统计出有十亿 的访问量或者十亿零十万的访问量其实是没有太多的区别的,因此,在这种业务场景下,为了节省成本,其实可以只计算出一个大概的值,而没有必要计算出精准的值

    这个数据结构的命令有三个:PFADD、PFCOUNT、PFMERGE
    redis> PFADD databases "Redis" "MongoDB" "MySQL"
    (integer) 1
     
    redis> PFADD databases "Redis"  # Redis 已经存在,不必对估计数量进行更新
    (integer) 0
    
    redis> PFCOUNT databases
    (integer) 3

    Geo 地理位置

    Redis 的 GEO 特性在 Redis 3.2 版本中推出, 这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作。GEO的数据结构总共有六个命令:geoadd、geopos、geodist、georadius、georadiusbymember、gethash,GEO使用的是国际通用坐标系WGS-84

    1.GEOADD:添加地理位置
    2.GEOPOS:查询地理位置(经纬度),返回数组
    3.GEODIST:计算两位位置间的距离
    4.GEORADIUS:以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
    5.GEORADIUSBYMEMBER:以给定的地理位置为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

    127.0.0.1:6379> geoadd kcityGeo 116.405285 39.904989 "beijing"
    (integer) 1
    127.0.0.1:6379> geoadd kcityGeo 121.472644 31.231706 "shanghai"
    (integer) 1 
    127.0.0.1:6379> geodist kcityGeo beijing shanghai km
    "1067.5980"
    127.0.0.1:6379> geopos kcityGeo beijing
    1) 1) "116.40528291463851929"
       2) "39.9049884229125027"
    127.0.0.1:6379> geohash kcityGeo beijing
    1) "wx4g0b7xrt0"
    127.0.0.1:6379> georadiusbymember kcityGeo beijing 1200 km withdist withcoord asc count 5
    1) 1) "beijing"
       2) "0.0000"
       3) 1) "116.40528291463851929"
          2) "39.9049884229125027"
    2) 1) "shanghai"
       2) "1067.5980"
       3) 1) "121.47264629602432251"
          2) "31.23170490709807012"

    内部编码

    但是,需要说明的是,Geo本身不是一种数据结构,它本质上还是借助于Sorted Set(ZSET),并且使用GeoHash技术进行填充。Redis中将经纬度使用52位的整数进行编码,放进zset中,score就是GeoHash的52位整数值。在使用Redis进行Geo查询时,其内部对应的操作其实就是zset(skiplist)的操作。通过zset的score进行排序就可以得到坐标附近的其它元素,通过将score还原成坐标值就可以得到元素的原始坐标。

    总之,Redis中处理这些地理位置坐标点的思想是:二维平面坐标点 --> 一维整数编码值 --> zset(score为编码值) --> zrangebyrank(获取score相近的元素)、zrangebyscore --> 通过score(整数编码值)反解坐标点 --> 附近点的地理位置坐标。

    应用场景

    比如现在比较火的直播业务,我们需要检索附近的主播,那么GEO就可以很好的实现这个功能。

    • 一是主播开播的时候写入主播Id的经纬度,
    • 二是主播关播的时候删除主播Id元素,这样就维护了一个具有位置信息的在线主播集合提供给线上检索。

    Streams 流

    这是Redis5.0引入的全新数据结构,用一句话概括Streams就是Redis实现的内存版kafka。支持多播的可持久化的消息队列,用于实现发布订阅功能,借鉴了 kafka 的设计。Redis Stream的结构有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,Redis重启后,内容还在。

            每个Stream都有唯一的名称,它就是Redis的key,在我们首次使用xadd指令追加消息时自动创建。

           每个Stream都可以挂多个消费组,每个消费组会有个游标last_delivered_id在Stream数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个Stream内唯一的名称,消费组不会自动创建,它需要单独的指令xgroup create进行创建,需要指定从Stream的某个消息ID开始消费,这个ID用来初始化last_delivered_id变量。

           每个消费组(Consumer Group)的状态都是独立的,相互不受影响。也就是说同一份Stream内部的消息会被每个消费组都消费到。

           同一个消费组(Consumer Group)可以挂接多个消费者(Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者者有一个组内唯一名称。

           消费者(Consumer)内部会有个状态变量pending_ids,它记录了当前已经被客户端读取的消息,但是还没有ack。如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack,它就开始减少。这个pending_ids变量在Redis官方被称之为PEL,也就是Pending Entries List,这是一个很核心的数据结构,它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理。

    • 消息ID:消息ID的形式是timestampInMillis-sequence,例如1527846880572-5,它表示当前的消息在毫米时间戳1527846880572时产生,并且是该毫秒内产生的第5条消息。消息ID可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的ID要大于前面的消息ID。
    • 消息内容:消息内容就是键值对,形如hash结构的键值对,这没什么特别之处。
    127.0.0.1:6379> XADD mystream * field1 value1 field2 value2 field3 value3
    "1588491680862-0"
    127.0.0.1:6379> XADD mystream * username lisi age 18
    "1588491854070-0"
    127.0.0.1:6379> xlen mystream
    (integer) 2
    127.0.0.1:6379> XADD mystream * username lisi age 18
    "1588491861215-0"
    127.0.0.1:6379> xrange mystream - + 
    1) 1) "1588491680862-0"
       2) 1) "field1"
          2) "value1"
          3) "field2"
          4) "value2"
          5) "field3"
          6) "value3"
    2) 1) "1588491854070-0"
       2) 1) "username"
          2) "lisi"
          3) "age"
          4) "18"
    3) 1) "1588491861215-0"
       2) 1) "username"
          2) "lisi"
          3) "age"
          4) "18"
    127.0.0.1:6379> xdel mystream 1588491854070-0 
    (integer) 1
    127.0.0.1:6379> xrange mystream - + 
    1) 1) "1588491680862-0"
       2) 1) "field1"
          2) "value1"
          3) "field2"
          4) "value2"
          5) "field3"
          6) "value3"
    2) 1) "1588491861215-0"
       2) 1) "username"
          2) "lisi"
          3) "age"
          4) "18"
    127.0.0.1:6379> xlen mystream
    (integer) 2

    内部编码

    streams底层的数据结构是radix tree:Radix Tree(基数树) 事实上就几乎相同是传统的二叉树。仅仅是在寻找方式上,以一个unsigned int类型数为例,利用这个数的每个比特位作为树节点的推断。能够这样说,比方一个数10001010101010110101010,那么依照Radix 树的插入就是在根节点,假设遇到0,就指向左节点,假设遇到1就指向右节点,在插入过程中构造树节点,在删除过程中删除树节点。如下是一个保存了7个单词的Radix Tree:

    应用场景总结

    实际上,所谓的应用场景,其实就是合理的利用Redis本身的数据结构的特性来完成相关业务功能


    常用内存优化手段与参数

    通过我们上面的一些实现上的分析可以看出 redis 实际上的内存管理成本非常高,即占用了过多的内存,作者对这点也非常清楚,所以提供了一系列的参数和手段来控制和节省内存,我们分别来讨论下。

    首先最重要的一点是不要开启 Redis 的 VM 选项,即虚拟内存功能,这个本来是作为 Redis 存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,但是其内存管理成本也非常的高,并且我们后续会分析此种持久化策略并不成熟,所以要关闭 VM 功能,请检查你的 redis.conf 文件中 vm-enabled 为 no。

     其次最好设置下 redis.conf 中的 maxmemory 选项,该选项是告诉 Redis 当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的 Redis 不会因为使用了过多的物理内存而导致 swap,最终严重影响性能甚至崩溃。

     另外 Redis 为不同数据类型分别提供了一组参数来控制内存使用,我们在前面详细分析过 Redis Hash 是 value 内部为一个 HashMap,如果该 Map 的成员数比较少,则会采用类似一维线性的紧凑格式来存储该 Map,即省去了大量指针的内存开销,这个参数控制对应在 redis.conf 配置文件中下面2项:

    hash-max-ziplist-entries 64
    hash-max-zipmap-value    512
    含义是当 value 这个 Map 内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即 value 内部有64个以下的成员就是使用线性紧凑存储,超过该值自动转成真正的 HashMap。hash-max-zipmap-value 含义是当 value 这个 Map 内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。以上2个条件任意一个条件超过设置值都会转换成真正的 HashMap,也就不会再节省内存了,那么这个值是不是设置的越大越好呢,答案当然是否定的,HashMap 的优势就是查找和操作的时间复杂度都是 O(1) 的,而放弃 Hash 采用一维存储则是 O(n) 的时间复杂度,如果成员数量很少,则影响不大,否则会严重影响性能,所以要权衡好这个值的设置,总体上还是最根本的时间成本和空间成本上的权衡。

    同样类似的参数还有

    list-max-ziplist-entries 512  
    
    说明:list 数据类型多少节点以下会采用去指针的紧凑存储格式。
    list-max-ziplist-value   64 
    说明:list 数据类型节点值大小小于多少字节会采用紧凑存储格式。
    set-max-intset-entries 512

    说明:set 数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。

    最后想说的是 Redis 内部实现没有对内存分配方面做过多的优化,在一定程度上会存在内存碎片,不过大多数情况下这个不会成为 Redis 的性能瓶 颈,不过如果在 Redis 内部存储的大部分数据是数值型的话,Redis 内部采用了一个 shared integer 的方式来省去分配内存的开销,即在系统启动时先分配一个从 1~n 那么多个数值对象放在一个池子中,如果存储的数据恰好是这个数值范围内的数据,则直接从池子里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下,也能一定程度上节省内存并且提高性能,这个参数值 n 的设置需要修改源代码中的一行宏定义 REDIS_SHARED_INTEGERS,该值 默认是 10000,可以根据自己的需要进行修改,修改后重新编译就可以了。

    展开全文
  • C51基本数据类型

    千次阅读 2019-12-19 13:42:36
    C51基本数据类型 C51中基本数据类型主要是指变量类型。变量是指其值可以改变的量。一个变量实质上是代表了内存中的某个存储单元。程序中的变量a,就是指用a命名的某个存储单元,用户对变量a进行的操作就是对该存储...

    C51基本数据类型

    C51中基本数据类型主要是指变量类型。变量是指其值可以改变的量。一个变量实质上是代表了内存中的某个存储单元。程序中的变量a,就是指用a命名的某个存储单元,用户对变量a进行的操作就是对该存储单元进行的操作;给变量a赋值,实质上就是把数据存人该变量所代表的内存单元中。

    变量有类型的区分,如整形变量、实型变量、字符型变量等。C语言在定义变量的同时说明该变量的类型,系统就能根据定义及其类型为它分配相应数量的存储空间。C51中变量类型与通用C语言基本相同,C51基本变量类型如表1.5.1所示。

    表1.5.1 C51基本变量类型

    数据类型

    长度

    值域

    unsigned char

    单字节

    0-255

    char

    单字节

    -128-127

    unsigned int

    双字节

    0-65535

    int

    双字节

    -32768-32767

    unsigned long

    四字节

    0-232-1

    long

    四字节

    -231-231-1

    float

    四字节

    3.4e-38-3.4e38

    *

    1-3字节

    对象的地址

    注:C51中int与short相同,float与double相同,在表中就不列出了。另外unsigned前缀表示无符号类型,无前缀表示有符号类型,即signed类型。

    每种基本变量类型介绍如下:

    (1)char类型

    即字符型变量,长度是一个字节,通常用于定义处理字符数据的变量或常量。分无符号字符类型unsigned char和有符号字符类型char,默认值为char类型。unsigned char类型用字节中所有的位来表示数值,所可以表达的数值范围是0~255。char类型用字节中最高位字节表示数据的符号,“0”表示正数,“1”表示负数,负数用补码表示。所能表示的数值范围是-128~+127。注意:这种数据类型在C51中最常见,因为51单片机是8位单片机,其内部寄存器绝大部分都是8位,故而8位字符变量与8位的字符型变量可以直接进行数据交换。

    (2)int类型

    即整型变量,长度为两个字节,用于存放一个双字节数据。分有符号整型数int和无符号整型数unsigned int,默认值为int类型。int表示的数值范围是-32768~+32767,字节中最高位表示数据的符号,“0”表示正数,“1”表示负数。unsigned int表示的数值范围是0~65535。

    (3)long类型

    即长整型变量,长度为四个字节,用于存放一个四字节数据。分有符号长整型long 和无符号长整型unsigned long,默认值为long类型。long表示的数值范围是-2147483648~+2147483647,字节中最高位表示数据的符号,“0”表示正数,“1”表示负数。unsigned long表示的数值范围是0~4294967295。

    (4)float类型

    即浮点型变量,在十进制中具有7位有效数字,是符合IEEE-754标准的单精度浮点型数据,占用四个字节。因浮点数的结构较复杂在此不做详细的讨论。另外由于double类型与float类型一样也是占用四个字节,故在此也不讨论。

    (5)*类型

    即指针类型,其本身就是一个变量,在这个变量中存放的指向另一个数据的地址。这个指针变量要占据一定的内存单元,对不同的处理器长度也不尽相同,在C51中它的长度一般为1~3个字节。

     

     

    展开全文
  • 简述java的8基本数据类型

    千次阅读 2019-03-11 12:44:57
    简述java的8基本数据类型 java基本数据类型就8,记住就好了。除了这些都是引用型的了。 java四类八基本数据类型 第一类:整型 byte short int long 第二类:浮点型 float double 第三类:逻辑型 boolean(它...

    简述java的8种基本数据类型

    java基本数据类型就8种,记住就好了。除了这些都是引用型的了。
    java四类八种基本数据类型
    第一类:整型 byte short int long
    第二类:浮点型 float double
    第三类:逻辑型 boolean(它只有两个值可取true false)
    第四类:字符型 char
    在栈中可以直接分配内存的数据是基本数据类型。
    引用数据类型:是数据的引用在栈中,但是他的对象在堆中。
    要想学好Java必须知道各种数据的在内存中存储位置。 对内存有了很好的了解,可以有助你分析程序。
    字节:
    boolean 布尔型 1/8
    byte 字节类型 1
    char 字符型 2 一个字符能存储一个中文汉字
    short 短整型 2
    int 整数类型 4
    float 浮点类型(单精度) 4
    long 长整形 8
    double 双精度类型(双精度) 8
    java中默认的整数类型是int类型,如果要定义为float型,则要在数值后加上l或L;
    默认的浮点型也是双精度浮点,如果要定义为float型,则要在数值后加上f或F。

    一个字节等于8位,一个字节等于256个数,就是-128到127一共256。
    kB就是kBytes Bytes就是“字节”的意思!
    K就是千的意思,因为计算机是通过二进制来计算,10个1正好是1024
    1111111111(二进制)=1024(十进制)
    1Bytes(字节)=8bit(比特)
    一个英文字母或一个阿拉伯数字就是一个字符,占用一个字节
    一个汉字就是两个字符,占用两个字节。
    一般讲大小是用Bytes,大写的“B”,讲网络速率是用bit,注意是小写的“b”。
    例:一个文件有8MBytes
    例:我下载文件的速率是256KB/s,即2Mbit,这通常就是我们宽带上网的速率。

    基本数据类型自动转换
    byte->short,char -> int -> long
    float -> double
    int -> float
    long -> double
    记住:小可转大,大转小会失去精度!!!

     

    Java八种基本数据类型

    1)四种整数类型(byteshortintlong): 

       byte8 位,用于表示最小数据单位,如文件中数据,-128~127 

       short16 位,很少用,-32768 32767 

       int32 位、最常用,-2^31-1~2^31  21 亿) 

       long64 位、次常用 

    2)两种浮点数类型(floatdouble): 

       float32 位,后缀 F 或 f,1 位符号位,8 位指数,23 位有效尾数。 

       double64 位,最常用,后缀 D 或 d,1 位符号位,11 位指数,52 位有效尾

    3)一种字符类型(char): 

       char16 位,是整数类型,用单引号括起来的 1 个字符(可以是一个中文字符),使用 Unicode 码代表字符,0~2^16-165535) 。 

    4)一种布尔类型(boolean):true 真  和 false 假。

    byte、shot、int、long、float、double、布尔(boolean)、char

    展开全文
  • 基本数据类型

    千次阅读 2017-11-06 15:44:25
    今天学习js基础,就又拿出高程看了一遍这几种数据类型。书尤其是技术类的书,看第二遍总是比第一遍收货的更多。以前看第一遍的时候到后面几乎是糊里糊涂的看完了,现在从新看了一遍才发现写代码时遇到的问题在这里都...
  • PHP数据类型有几

    千次阅读 2019-03-07 19:26:50
    一、PHP分为三种数据类型: 标量数据类型 符合数据类型 特殊数据类型 1. 数据类型分类 2. 数据类型解析 1. boolean(布尔型) 布尔型是PHP中较常用的数据类型之一,通常用于逻辑判断。布尔值分为true(真)和...
  • ClickHouse数据类型

    千次阅读 2020-09-27 14:41:30
    文章目录ClickHouse数据类型基础类型数值类型整数浮点数Decimal字符串类型StringFixedStringUUID时间类型DateDateTimeDateTime64复合类型数组元组枚举嵌套特殊类型NullableDomain参考文档 ClickHouse数据类型 ...
  • JS基础篇1:数据类型(8

    万次阅读 多人点赞 2019-07-08 19:27:23
    最近有很多人说数据类型是 6。我怎么记得JS的数据类型有8。最近发现好多人对JS的基础不太了解。很多数据类型都没有搞清楚。不BB,我就按我的理解写一波笔记,每次看一波书我就感觉一次比一次多懂一点。来补下...
  • Python 入门&环境搭建&变量&数据类型

    千次阅读 多人点赞 2019-09-16 18:36:07
    是一面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。 Python 应用领域: Python 是一解释型脚本语言,可以应用...
  • Java 基本数据类型 - 四类八

    万次阅读 多人点赞 2018-06-13 09:57:29
    一、Java四大数据类型分类1、整型byte 、short 、int 、long2、浮点型float 、 double3、字符型char4、布尔型boolean二、八基本数据类型三、数据类型详细介绍整型(byte、short、int、long)虽然byte、short、int...
  • 目录 目前的状态 史蒂文斯的测量类型学 7种机器学习的主要数据类型 1.无用的 2.形同虚设 ...我如何记住这7种数据类型...我应该传播有关7种数据类型的信息吗? 在本文中,我为机器学习从业者提出了一种更有用的...
  • Java数据类型(八大基本数据类型):六数字类型(四个整数型,两个浮点型),一 字符类型,还有一布尔型。 1. 整值型: (1) 整型 :(byte、short、int、)----- 默认值:0 (2)Long-----------------------...
  • C++基本数据类型

    千次阅读 2018-04-21 11:14:51
    内置的C++类型分为两组:基本类型...整型分为char, short, int, long, long long,每种类型都有符号和无符号类型,即10。加上bool类型,一共11。每种类型的最小长度: char:8位(bit,8bit=1Byte) short:1...
  • 浮点型数据类型

    万次阅读 2020-03-06 20:52:25
    浮点型常量有两表示形式:进制小数形式和指数形式。 3.3.21.1 代码实践,两表达方式的实现 3.3.21.2 实型常量的类型细分:默认为double型,例如3.14就是double类型, 后面加f或F认为是float型,例如3.14f...
  • jQuery数据类型

    千次阅读 2018-11-08 15:17:11
    js数据类型:7 基本数据类型: 字符串 , 数值, 布尔 复合(引用数据类型): 对象, 数组 特殊数据类型: null, undefined 注意:  1.在 Jscript 中整数和浮点值没有差别  2.另外,JScript包含特殊值数字。它们是:  ...
  • byte范围及8常见数据类型

    万次阅读 2016-07-24 13:19:24
    在计算机内,定点数有3表示法:原码、反码和补码 原码 :二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。 反码 :正数的反码与其原码相同;负数的反码是对其原码逐位取反...
  • JS中六种数据类型(四)——Number

    万次阅读 2016-04-21 22:16:53
    Number类型应该是ECMAScript中最令人关注的数据类型了,这种类型使用IEEE754格式来表示整数和浮点数值(浮点数值在某些语言中也被称为双精度数值)。为支持各种数值类型,ECMA-262定义了不同的数值字面量。  最基本...
  • 易语言认识易语言数据类型

    千次阅读 2020-06-21 10:31:29
    数据:是指能够输入致计算机,并被计算机识别和加工处理的符号的集合。数据按一定的标准分为不同的类型,易语言称其数据类型。易语言的数据类型从数据结构区分,可分为基本数据类型、...基本数据类型有6:数值型、逻
  • 一、基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768~32717,默认值0 int:整型,用于存储...
  • sql server 2008 的数据类型大全

    千次阅读 2021-03-31 11:13:54
    #数据库sql server 的数据类型 1.精确数字类型 (1)整数类型包括以下几。 bigint:可以存储-9223372036854775808~ 9223372036854775807范围内的所有整型数据,每个bigint数据类型值存储在8字节中。 **int(integer)???...
  • MySQL数据库中的5种数据类型简介

    千次阅读 2014-01-13 13:47:05
    MySQL数据库中的5种数据类型是:字符型,文本型,数值型,逻辑型与日期型,以下就是文章的详细内容介绍,希望在你今后的学习中会有所帮助。 MySQL数据类型之一字符型 VARCHAR VS CHAR VARCHAR型和CHAR型数据...
  • 标识符:用来标识程序中用到的变量名、函数名、类型名、数组名、文件名以及符号常量名的有效字符序列。 语法规则(部分): 标识符只能是由英文字母、数字和下划线组成的字符串,并且第一个字符必须为字母或下划线...
  • Int数据类型详解

    万次阅读 2018-04-08 15:42:27
    Int 4kb,32bit,范围 -2147483648 到 2147483647 ...三表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三表示方法各不相同。 在计算机系统中,数值一律...
  • r中将数据框中数据类型转化Before we delve deeper into R programming, it is important to understand the various data types used in R. R has the following basic data types: 在深入研究R编程之前 ,了解R中...
  • 【前端】—JS 中的数据类型

    千次阅读 2018-04-22 21:24:38
    前言 &nbsp;&...Java Script中的数据类型分为6,两类:简单数据类型和复杂数据类型,简单数据类型包括 Number、Undefined、Null、Boolean 和String,复杂数据类型是Object。 数据类型...
  • 基本数据类型的精度和范围

    万次阅读 多人点赞 2018-09-17 21:49:34
    Java中的数据类型分为:基本数据类型和引用数据类型。如下图所示: 下面主要要讨论的是基本数据类型的数据表示范围是如何得到的。 1.首先应该对计算机的存储单元有一定的了解。 在计算机里无论是内存还是...
  • JAVA八基本数据类型-字节数和取值范围Java8基本数据类型: 类型 字节 位数 取值范围 默认值 包装类 boolean 1/8 1 true, false false Boolean byte 1 8 -128-127 0 Byte short 2 16 -...
  • Impala数据类型

    万次阅读 2017-10-20 14:59:08
    数据类型及说明 BIGINT 此数据类型存储数值,此数据类型的范围为-9223372036854775808至9223372036854775807.此数据类型在create table和alter table语句中使用。 BOOLEAN 此数据类型只存储true或false值,它...
  • 深入理解Python中的基本数据类型

    千次阅读 2017-05-08 21:53:45
    博客核心内容:1、进制、编码、解码的相关概念 2、类和对象的相关概念 3、基本类型之字符串功能介绍 ...10、基本类型之set集合类型介绍1、进制、编码、解码的相关概念本篇博客的重点在于介绍Pyt
  • PostgreSQL 数据类型

    千次阅读 2017-11-06 20:13:06
    PostgreSQL 数据类型 ...PostgreSQL 的数据类型被分为四,分别是基本数据类型、复合数据类型、域和伪类型。    基本数据类型是数据库内置的数据类型,包括integer、char、varchar等数据类型。表6-1列出了Postg

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 512,316
精华内容 204,926
关键字:

十种数据类型