2、使用jdbc查询数据库,一行数据对应一个实体对象,放进一个集合List<entity>中。
在之前的文章中我们有提及string类型是通过底层的SDS(简单动态字符串)实现的,那么其他呢?
除了String类型外,list,set,sorted set,hash这四种都有两种底层实现结构,通常情况我们称这四种类型为集合类型, 特点是一个键对应了一个集合的数据 :
list由双向链表和压缩列表实现
hash由压缩列表和哈希表实现
sorted set由跳表和压缩列表实现
set 由整数数组和哈希表实现
·1.压缩列表在查找和更新的时间复杂度方面没有很大的优势,为什么redis要把他作为底层数据结构?
2.集合数据的 *** 作效率
list由双向链表和压缩列表实现
阅读src/ziplist.h和src/ziplist.c我们惊奇的发现一件事情:
redis竟没有提供一个结构体保存压缩列表的信息,而是提供了一组宏来定义每个成员的地址
压缩列表是一系列 特殊编码的连续内存块 组成的顺序序列数据结构,可以包含任意多个节点(entry),每一个节点可以保存一个字节数组或者一个整数值。
这个数据结构是不是乍一看很像数组,每一个元素entry保存了一个数据,和数组不同的是表头有三个字段:
1.zlbytes标识整个压缩列表长度
2.zltail标识列表的偏移量,表尾点entryN距离压缩列表起始地址的字节数
3.zllen标识列表中entry个数
列表表尾还有一个zlend标识结束
那么我们就可以快速定位第一个元素(zlbytes-10)和最后一个元素(zlbytes-1)了
ziplist的每个节点由3个部分组成:
1.prevlen表示前一个节点的长度
2.encoding表示节点的编码格式
3.entry-data:压缩后的数据
zpilist格式
<zlbytes><zltail><zllen><entry><entry>... <entry><zlend>
zlbytes:ziplist占总字节数
zltail:最后一个元素的偏移量,相当于ziplist的尾指针。
zllen:entry元素个数
zlend :ziplist结束标志位
entry:ziplist的各个节点
ziplist的entry 的格式:
<prevlen><encoding><len><entry-data>
prevlen :前一个元素的长度,相当于节点保存前一个元素的指针。
encoding: 记录了当前节点保存的数据的类型以及当前节点长度,相当于节点保存后一个元素的指针。
len:自身长度
entry-data :经过压缩后的数据
quciklist结构实现
其中节点实现
我们阅读结构体发现虽然是quicklist但却出现了很多关于ziplist的身影
首先ziplist的插入和删除 *** 作时间复杂度非常高(参考数组需要重新生成一个ziplist来作为更新后的list),当一个list非常大的且更新平凡就会带来非常大的开销。
所谓的quicklist就是把ziplist和普通的双向链表解和,每个双向节点保存一个ziplist,每个ziplist中存一批list数据,这样可以避免大量链表指针 *** 作带来的内存开销(即化整为零思想)
Redis对外暴露的list数据结构,其底层实现所依赖的内部数据结构就是quicklist。quicklist就是一个块状的双向压缩链表。
考虑到双向链表在保存大量数据时需要更多额外内存保存指针并容易产生大量内存碎片,以及ziplist的插入删除的高时间复杂度,两个数据结构的缺陷会导致在数据量很大或插入删除 *** 作频繁的极端情况时,性能极其低下。
Redis为了避免数据结构在极端情况下的低性能,将双向链表和ziplist综合起来,成为了较双向链表及ziplist性能更加稳定的quicklist
1.压缩列表在查找和更新的时间复杂度方面没有很大的优势,为什么redis要把他作为底层数据结构?
list底层使用压缩列表本质上是将所有元素紧挨着存储,能节省空间避免内存碎片(内存空间不是硬盘空间是很昂贵的)
有序列表查找元素,只能遍历查找,于是就出现了跳表
skiplist节点结构体
也就是说跳表在链表的基础上增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位
其中索引可以持续累加
整数数组是集合的底层实现之一,当一个集合只包含整数元素且数量不多,就会用该方式实现
2.集合数据的 *** 作效率
mysql怎么获取数据表字段enum类型的默认值本节主要内容:
MySQL数据类型之枚举类型ENUM
MySQL数据库提供针对字符串存储的一种特殊数据类型:枚举类型ENUM,这种数据类型可以给予我们更多提高性能、降低存储容量和降低程序代码理解的技巧,前面介绍了首先介绍了四种数据类型的特性总结,其后又分别介绍了布尔类型BOOL或称布尔类型BOOLEAN,以及后续会再单独介绍集合类型SET。
本文详细介绍集合类型enum测试过程与总结,加深对mysql数据库集合类型enum的理解记忆。
n 枚举类型ENUM
a).数据库表mysqlops_enum结构
执行数据库表mysqlops_enum创建的SQL语句:
复制代码代码示例:
root@localhost : test 11:22:29>CREATE TABLE Mysqlops_enum(ID INT NOT NULL AUTO_INCREMENT,
-> Job_typeENUM('DBA','SA','Coding Engineer','JavaScript','NA','QA','','other') NOT NULL,
-> Work_City ENUM('shanghai','beijing','hangzhou','shenzhen','guangzhou','other') NOT NULL DEFAULT 'shanghai',
-> PRIMARY KEY(ID)
-> )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'
Query OK, 0 rows affected (0.00 sec)
执行查询数据库表mysqlops_enum结构的SQL语句:
复制代码代码示例:
root@localhost : test 11:23:31>SHOW CREATE TABLE Mysqlops_enum\G
*************************** 1. row ***************************
Table: Mysqlops_enum
Create Table: CREATE TABLE `Mysqlops_enum` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Job_type` enum('DBA','SA','Coding Engineer','JavaScript','NA','QA','','other') NOT NULL,
`Work_City` enum('shanghai','beijing','hangzhou','shenzhen','guangzhou','other') NOT NULL DEFAULT 'shanghai',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
小结:
为方便测试枚举类型,如何处理字段定义的默认值、是否允许为NULL和空值的情况,我们定义了2个枚举类型的字段名,经过对比创建与查询数据库中表的结构信息,没有发现MySQL数据库默认修改任何信息。
b). 写入不同类型的测试数据
写入一条符合枚举类型定义的记录值:
复制代码代码示例:
root@localhost : test 11:22:35>INSERT INTO Mysqlops_enum(ID,Job_type,Work_City) VALUES(1,'QA','shanghai')
Query OK, 1 row affected (0.00 sec)
测试第二个枚举类型字Work_City是否允许为空记录值:
复制代码代码示例:
root@localhost : test 11:22:42>INSERT INTO Mysqlops_enum(ID,Job_type,Work_City) VALUES(2,'NA','')
Query OK, 1 row affected, 1 warning (0.00 sec)
root@localhost : test 11:22:48>SHOW WARNINGS
+---------+------+------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------+
| Warning | 1265 | Data truncated for column 'Work_City' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)
测试第二个枚举类型字段Work_City是否允许存储NULL值:
复制代码代码示例:
root@localhost : test 11:22:53>INSERT INTO Mysqlops_enum(ID,Job_type,Work_City) VALUES(3,'Other',NULL)
ERROR 1048 (23000): Column 'Work_City' cannot be null
测试第一个枚举类型字段Job_type是否可以存储空白值:
复制代码代码示例:
root@localhost : test 11:22:59>INSERT INTO Mysqlops_enum(ID,Job_type,Work_City) VALUES(4,'','hangzhou')
Query OK, 1 row affected (0.00 sec)
测试第二个枚举类型字段Job_City如何处理没有在定义中描述的值域第一个枚举类型字段Work_Type的默认值没指定情况下,会默认填写那个值:
复制代码代码示例:
root@localhost : test 11:23:06>INSERT INTO Mysqlops_enum(ID,Work_City) VALUES(5,'ningbo')
Query OK, 1 row affected, 1 warning (0.00 sec)
root@localhost : test 11:23:13>SHOW WARNINGS
+---------+------+------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------+
| Warning | 1265 | Data truncated for column 'Work_City' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)
测试第二个枚举类型字段未插入数据的情况下,是否能使用上字段定义中指定的默认值:
复制代码代码示例:
root@localhost : test 11:23:17>INSERT INTO Mysqlops_enum(ID,Job_type) VALUES(6,'DBA')
Query OK, 1 row affected (0.00 sec)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)