关系数据库与非关系型数据库

关系型数据库

关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户通过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。

特点

存储方式:

传统的关系型数据库采用表格的储存方式,数据以行和列的方式进行存储,要读取和查询都十分方便。

存储结构:

关系型数据库按照结构化的方法存储数据,每个数据表都必须对各个字段定义好(也就是先定义好表的结构),再根据表的结构存入数据,这样做的好处就是由于数据的形式和内容在存入数据之前就已经定义好了,所以整个数据表的可靠性和稳定性都比较高,但带来的问题就是一旦存入数据后,如果需要修改数据表的结构就会十分困难。

存储规范:

关系型数据库为了避免重复、规范化数据以及充分利用好存储空间,把数据按照最小关系表的形式进行存储,这样数据管理的就可以变得很清晰、一目了然,当然这主要是一张数据表的情况。如果是多张表情况就不一样了,由于数据涉及到多张数据表,数据表之间存在着复杂的关系,随着数据表数量的增加,数据管理会越来越复杂。

扩展方式:

由于关系型数据库将数据存储在数据表中,数据操作的瓶颈出现在多张数据表的操作中,而且数据表越多这个问题越严重,如果要缓解这个问题,只能提高处理能力,也就是选择速度更快性能更高的计算机,这样的方法虽然可以一定的拓展空间,但这样的拓展空间一定有非常有限的,也就是关系型数据库只具备纵向扩展能力。

查询方式:

关系型数据库采用结构化查询语言(即SQL)来对数据库进行查询,SQL早已获得了各个数据库厂商的支持,成为数据库行业的标准,它能够支持数据库的CRUD(增加,查询,更新,删除)操作,具有非常强大的功能,SQL可以采用类似索引的方法来加快查询操作。

规范化:

在数据库的设计开发过程中开发人员通常会面对同时需要对一个或者多个数据实体(包括数组、列表和嵌套数据)进行操作,这样在关系型数据库中,一个数据实体一般首先要分割成多个部分,然后再对分割的部分进行规范化,规范化以后再分别存入到多张关系型数据表中,这是一个复杂的过程。好消息是随着软件技术的发展,相当多的软件开发平台都提供一些简单的解决方法,例如,可以利用ORM层(也就是对象关系映射)来将数据库中对象模型映射到基于SQL的关系型数据库中去以及进行不同类型系统的数据之间的转换。

事务性:

关系型数据库强调ACID规则(原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)),可以满足对事务性要求较高或者需要进行复杂数据查询的数据操作,而且可以充分满足数据库操作的高性能和操作稳定性的要求。并且关系型数据库十分强调数据的强一致性,对于事务的操作有很好的支持。关系型数据库可以控制事务原子性细粒度,并且一旦操作有误或者有需要,可以马上回滚事务。

读写性能:

关系型数据库十分强调数据的一致性,并为此降低读写性能付出了巨大的代价,虽然关系型数据库存储数据和处理数据的可靠性很不错,但一旦面对海量数据的处理的时候效率就会变得很差,特别是遇到高并发读写的时候性能就会下降的非常厉害。

授权方式:

关系型数据库常见的有 Oracle,SQLServer,DB2,Mysql,除了Mysql大多数的关系型数据库如果要使用都需要支付一笔价格高昂的费用,即使是免费的Mysql性能也受到了诸多的限制。

设计步骤

关系型数据库设计的过程可大体分为四个时期七个阶段。
(1)用户需求分析时期,主要是了解和分析用户对数据的功能需求和应用需求,是整个设计过程的基础,事关整个数据库应用系统设计的成败。

(2)数据库设计时期,主要是将用户需求进行综合、归纳与抽象,形成一个独立于具体DBMS的数据模型,可用实体—联系模型来表示,然后将其转换为已选好的关系型数据库管理系统RDBMS所支持的一组关系模式并为其选取一个适合应用环境的物理结构,包括存储结构和存取方法。

(3)数据库实现时期,包括数据库结构创建阶段和应用行为设计与实现阶段,是根据数据库的物理模型创建数据库、创建表、创建索引、创建聚簇等。

(4)数据库运行与维护阶时期,最后一个阶段则是数据库应用系统经过试运行后即可投入正式运行。

设计原则

在进行关系型数据库的设计过程中,要遵循以下几个原则,借此可以提高数据库的存储效率、数据完整性和可扩展性。

命名规范化

在概念模型设计中,对于出现的实体、属性及相关表的结构要统一。例如在数据库设计中,指定学生Sstudent,专指本科生,相关的属性有:学号、姓名、性别、出生年月等,及每个属性的类型、长度、取值范围等都要进行确定,这样就能保证在命名时不会出现同名异义或异名同义、属性特征及结构冲突等问题。

数据的一致性和完整性

在关系型数据库中可以采用域完整性、实体完整性和参照完整性等约束条件来满足其数据的一致性和完整性,用check、default、null、主键和外键约束来实现。

数据冗余

数据库中的数据应尽可能地减少冗余,这就意味着重复数据应该减少到最少。例如:若一个部门职员的电话存储在不同的表中,假设该职员的电话号码发生变化时,冗余数据的存在就要求对多个表进行更新操作,若某个表不幸被忽略了,那么就会造成数据不一致的情况。所以在数据库设计中一定要尽可能存在少地冗余。

范式理论

在关系数据库设计时,一般是通过设计满足某一范式来获得一个好的数据库模式,通常认为3NF在性能、扩展性和数据完整性方面达到了最好的平衡,因此,一般数据库设计要求达到3NF,消除数据依赖中不合理的部分,最终实现使一个关系仅描述一个实体或者实体间一种联系的目的。

常用关系型数据库

主流的关系型数据库有Oracle、DB2、MySQL、Microsoft SQL Server、Microsoft Access等多个品种,每种数据库的语法、功能和特性也各具特色。

Oracle数据库是由甲骨文公司开发,并于1989年正式进入中国市场。虽然当时的Oracle尚名不见经传,通过多年的发展积聚了众多领先性的数据库系统开发经验,在集群技术、高可用性、安全性、系统管理等方面都取得了较好的成绩。Oracle产品除了数据库系统外,还有应用系统、开发工具等。在数据库可操作平台上,Oracle可在所有主流平台上运行,因而可通过运行于较高稳定性的操作系统平台,提高整个数据库系统的稳定性。

MySQL数据库是一种开放源代码的关系型数据库管理系统(RDBMS),可以使用最常用结构化查询语言进行数据库操作。也因为其开源的特性,可以在General Public License的许可下下载并根据个性化的需要对其进行修改。MySQL数据库因其体积小、速度快、总体拥有成本低而受到中小企业的热捧,虽然其功能的多样性和性能的稳定性差强人意,但是在不需要大规模事务化处理的情况下,MySQL也是管理数据内容的好选择之一。

Microsoft SQL Server数据库最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发的,于1988 年推出了第一个操作系统版本。在Windows NT 推出后,Microsoft 将SQL Server 移植到Windows NT系统上,因而SQL Server数据库伴随着Windows操作系统发展壮大,其用户界面的友好和部署的简捷,都与其运行平台息息相关,通过Microsoft的不断推广,SQL Server数据库的占有率随着Windows操作系统的推广不断攀升。

非关系型数据库

非关系型数据库,也称NoSQL数据库,采用不同于关系数据“行列”组织的数据模型,可以混合支持多种数据类型。对比关系型数据库,NoSQL数据库采用更简单的设计方式,更灵活的数据模型,在设计上有着更好的扩展能力,这使得NoSQL数据库能更有效地应对数据负载超过单个服务器承载能力的应用场景。

NoSQL数据库是非关系型数据库的统称,其中 “No”指的是“Not Only”,表示不止于SQL。

特点

格式灵活:

存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。

速度快:

nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;

高扩展性;

分区容忍性高,数据结构不存在复杂关系,因而更易于”水平”扩展到多台机 器,能够提供高吞吐量的服务。

成本低:

nosql数据库部署简单,基本都是开源软件。

劣势

无法处理ACID事务,仅能保证最终一致性:对数据的修改“最终”传播 到所有节点(通常在几毫秒内),因此对数据的查询可能不会立即返回更新的数据或可能导致 读取数据不准确,称为陈旧读取的问题。

此外,一些NoSQL系统可能会出现写入丢失和其 他形式的数据丢失,可根据日志内容,在必要时恢复真实数据值。 NoSQL 数据库天然运行在分布式环境下,因此需要考虑分布式下的数据一致性问题,这使 得NoSQL的数据一致性的要求与传统关系数据库相比发生了很大的变化。

非关系型数据库分类

非关系型数据库,根据数据类型划分,主要包括:键值数据库、文档数据库、列簇式数据库、图数据库、时序数据库等。

键值数据库

键值数据库业界代表包括 Redis、RocksDB、DynamoDB等。

文档数据库

文档型数据库业界代表包括 MongoDB、CouchDB等。

列簇式数据库

列簇式数据库业界代表包括 BigTable、HBase、Cassandra等。

图数据库

图数据库业界代表包括 Neo4J、Spark GraphX、GraphLab PowerGraph、PyTorch-BigGraph等。

时序数据库

时序数据库业界代表包括 InfluxDB、OpenTSDB等。

空间数据库

空间数据库业界代表包括 PostGIS、Geomesa等。

非关系型数据库产生背景

可用于应对 Web2.0 纯动态网站类型的三高问题。
(1)High performance——对数据库高并发读写需求
(2)Huge Storage——对海量数据高效存储与访问需求
(3)High Scalability && High Availability——对数据库高可扩展性与高可用性需求

关系型数据库和非关系型数据库区别

数据存储方式不同

关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。
与其相反,非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。

扩展方式不同

SQL和NoSQL数据库最大的差别可能是在扩展方式上,要支持日益增长的需求当然要扩展。
要支持更多并发量,SQL数据库是纵向扩展,也就是说提高处理能力,使用速度更快速的计算机,这样处理相同的数据集就更快了。因为数据存储在关系表中,操作的性能瓶颈可能涉及很多个表,这都需要通过提高计算机性能来克服。虽然SQL数据库有很大扩展空间,但最终肯定会达到纵向扩展的上限。
而NoSQL数据库是横向扩展的。因为非关系型数据存储天然就是分布式的,NoSQL数据库的扩展可以通过给资源池添加更多普通的数据库服务器(节点)来分担负载。

对事务性的支持不同

如果数据操作需要高事务性或者复杂数据查询需要控制执行计划,那么传统的SQL数据库从性能和稳定性方面考虑是你的最佳选择。SQL数据库支持对事务原子性细粒度控制,并且易于回滚事务。
虽然NoSQL数据库也可以使用事务操作,但稳定性方面没法和关系型数据库比较,所以它们真正闪亮的价值是在操作的扩展性和大数据量处理方面。

小结

非关系数据库

1、数据保存在缓存中,利于读取速度/查询数据
2、架构中位置灵活
3、分布式、扩展性高
非关系型数据库数据流向:
实例–>数据库–>集合(collection)–>键值对(key-value)

关系数据库

1、安全性高(持久化)
2、事务处理能力强
3、任务控制能力强
4、可以做日志备份、恢复、容灾的能力更强一点。
关系型数据库数据流向:
实例–>数据库–>表(table)–>记录行(row)、数据字段(column)------》存储数据

redis优化

redis都是基于内存的操作,CPU不是redis的性能瓶颈,则服务器的内存利用率和网络IO就是redis的性能瓶颈,redis优化主要是从这2个维度做优化。

内存淘汰优化

杜绝使用默认的内存淘汰策略,避免在业务扩展下Redis的内存持续膨胀,需要根据你的业务设置对应内存淘汰策略。

过期策略优化

由于redis采用的是定期删除+懒加载删除策略,且这个过程在redis 6.0之前是在主线程上执行的,
建议所有key的过期时间用随机数打散,杜绝大批量的数据同时过期,拉胯redis的性能和造成缓存雪崩。

数据存储优化

控制key的长度
在保证key在简单、清晰的前提下,尽可能把key定义得短一些来控制key的长度,如 uerOreder:0001 缩写为uo:0001。
建议:做好key规范管理的文档,定义好每个key缩写的含义。
如按以上规范来做当redis中有大量的key时也会节约redis大量的内存空间,使其性能更高
控制元素的大小
在决定使用redis建议强制规定元素的大小,推荐规范如下:
	1. String类型数据的值控制在10K以下;
	2. List/Hash/Set/ZSet数据类型的元素要控制在1W以内。
以上的是杜绝bigkey有效措施,在bigkey对redis的性能影响是最为致命的。
存储合适数据类型
除非业务的强要求,建议选择合适的数据类型来优化内存,具体如下:
	1. String、Set:尽可能存储 int 类型数据;
	2. Hash、ZSet:存储的元素数量控制在转换阈值之下,以压缩列表存储,节约内存。
设置过期key
强制要求所有的key必须设置过期时间,以优化redis内存。
冷热分离
热key需要单独存放并分配合理的资源,防止大流量下直接冲垮整个缓存系统。
数据压缩
可以采用snappy、gzip 等压缩算法来先将数据压缩后再存入缓存中,来节约redis的内存空间,但这种方法会使客户端在读取时还需要解压缩,在这期间会消耗更多CPU资源,你需要根据实际情况进行权衡。
建议,只是在redis匮乏时的一种方案。

持久化优化

除非业务的强要求,否则不要开启AOF,避免写磁盘拖垮redis的性能。
如果有业务要求开启AOF,建议配置为 appendfsync everysec 把数据持久化的刷盘操作,
放到后台线程中去执行,尽量降低 Redis 写磁盘对性能的影响。

部署优化

物理机部署
Redis在做数据持久化时,采用创建子进程的方式进行( 会调用操作系统的 fork 系统 ),而 虚拟机环境执行 fork 的耗时,要比物理机慢得多。
内网部署
Redis集群有做副本数据同步,为了解决网络问题建议整个集群都部署在同一个局域网中。

集群优化

只使用db0
具体原因如下:
	1.在一个连接上操作多个db数据时,每次都会先执行查询,有额外开销;
	2.建议不同业务数据尽量存储到不同的实例中而不是存放在不同db中;
	3.redis cluster只支持db0。
架构优化
读写分离能最大限度提高redis的性能,其中主库负责数据写入,从库负责数据读取;分片集群是解决超大量数据导致性能瓶颈方案,如rediscluster。
以上是在大流量下提高redis性能在架构上的优化。
实例内存优化
Redis集群有做副本数据同步,如果redis的内存过大,那么在做持久化或数据同步时,
磁盘IO和网络IO会拉垮redis性能,导致卡顿。
建议redis每一个实例都不要超过8G,要从业务上解耦,不同的业务用不同的redis实例,
杜绝所有业务都使用同一个redis实例。

其他优化

lazy-free机制
在redis4.0+中支持,开启lazy-free机制后,由主线程删除bigkey,而较耗时的内存释放会在后台线程中执行,不会影响到主线程。
批量命令
尽量减少客户端和服务端之间来回的io次数,建议string/hash使用mget/mset代替get/set,
hmget/hmset代替hget/hset;其他数据类型使用pipeline。
避免复杂度过高命令
redis是单线程模型处理请求,在执行复杂度过高的命令(消耗更多cpu资源)时后面的请求会排队导致延迟,
如 SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE 等聚合类命令
注意容器类型数据
1. 容器类型数据查询
ist、hash、set、zset类型数据在查询时要先确认元素的数量,元素非常多时需要分批查询( LRANGE/HASCAN/SSCAN/ZSCAN ),否则大量数据会导致延迟(如网络传输问题等)。
	2. 容器类型数据删除
建议分批删除,如list执行多次lpop/rpop;hash/set/zset先执行hscan/sscan/scan查询元素,再执行hdel/srem/zrem,不关注元素的数量直接del会有大量内存释放,拖垮主线程性能。