1700509321
1700509322
从数据的组织形式来说,目前有两大类,一类是RDBMS(关系型数据库管理系统,Relational Database Management System),另一类是NoSQL(2)。
1700509323
1700509324
RDBMS通常用数据库、表、字段3层对数据进行描述。这种结构应用非常广泛,历史悠久,普及性极高。在这类数据库中,一个数据库(Database)下可以建立若干个表(Table),一个表中可以建立若干个字段(Field)。在一个表的内部,每一行数据都必须具有相同的字段描述。
1700509325
1700509326
NoSQL通常是用数据库、表、键值对3层对数据进行描述。一个数据库下可以建立若干个表。NoSQL和RDBMS的区别在于,NoSQL表内部不设置字段,表内部的每一行数据都用Key-Value键值对来描述,也就是说,每一行的字段都可以不同。
1700509327
1700509328
乍一看这只是形式上不同,其功能都是存储数据,但是它们的使用场景有着比较大的区别。RDBMS注重关系,并且在查找引擎上注重对多表联查(3)的支持和优化,适合做复杂的多维数据分析。而NoSQL表天生就是一种稀疏矩阵的数据逻辑架构,适用于那种在大量不规则的数据结构中查找一条数据的场景,例如博客系统等。由于多表查询很不方便,所以在供分析的数据存储场景中,通常不推荐使用NoSQL类型的数据库。
1700509329
1700509330
在数据量非常大且预算有限的情况下,还是推荐使用开源的Hive、SparkSQL或者PrestoDB on HDFS。这类数据仓库对海量数据的支持特性非常优秀,而且有丰富的文档可以参考。
1700509331
1700509332
1700509333
1700509334
1700509336
数据科学家养成手册 13.4 要不要支持事务
1700509337
1700509338
对于在线数据库OLTP来说,事务通常是比较重要的。事务是指那种一次涉及多个表、多条数据的写操作(4),要求是要么都生效,要么都不生效。
1700509339
1700509340
事务在对业务提供线上支持的数据库中是非常重要的,尤其是对涉及支付的系统,更是必需的。不过,我们所说的日志分析场景中的数据不一定是必需的,而且在我的工作经验中,没有事务的情况似乎更好、更自由。
1700509341
1700509342
在数据分析场景中,通常会使用OLAP数据仓库。常见的OLAP数据仓库有Oracle、DB2、Teradata、Greenplum等。这些数据仓库的特点是吞吐量比较大,尤其是对多表联查的效率支持很高,而其缺点也非常明显,例如对一次涉及几条数据的小事务来说性能支持非常不好。
1700509343
1700509344
如果觉得上述这些数据仓库价格高昂,还有Hive、SparkSQL、PrestoDB on HDFS可以选择。这些分布式数据仓库通常有更高的单次访问延迟,不过这种代价对于OLAP的场景来说无足轻重,关键是获得了极高的可扩展性和大规模数据的读写性能。这个性能的提升主要通过“读写分散”获得,下面我们就以Hive为范例进行讲解。
1700509345
1700509346
Hive在底层是基于HDFS和MapReduce的,写入集群时遵循HDFS的写入原则。只要向Hive的数据仓库里写数据,就必须使用诸如
1700509347
1700509348
LOAD DATA LOCAL INPATH ‘/Linklog_20161122.txt’ OVERWRITE INTO TABLE Linklog PARTITION(dt=‘20161122’);
1700509349
1700509350
这种语句。
1700509351
1700509352
以上语句实际上就是把本地文件“/Linklog_20161122.txt”复制到集群hdfs:///user/hive/ warehouse中去。这里为什么不使用事务呢?因为在OLAP环境中,数据一般都是已经存在的历史数据,几乎没有回退的机会。如果一定要使用事务,就必须有与Oracle结构相同的更新逻辑。
1700509353
1700509354
以更新一个数据块D为例,如图13-6所示。
1700509355
1700509356
1700509357
1700509358
1700509359
图13-6 事务中的Undo和Redo
1700509360
1700509361
(1)要更新数据块D的时候,为了保证事务隔离,首先必须保证其他事务能访问提交前的数据块D,此时会生成一个Undo块信息U来记录数据块D更新前的信息。
1700509362
1700509363
(2)生成一个Redo信息来记录Undo块涉及的修改内容,包括U的地址、U的内容、事务标识(事务号)。
1700509364
1700509365
(3)修改数据块D的内容,同时产生一个Redo信息,包括数据块D的地址、数据块D修改后的内容、事务标识。
1700509366
1700509367
如果此时用户提交了Commit命令,那么Undo块信息U的内容就会被释放,事务将无法回滚。如果此时提交了Rollback命令,那么数据块D的内容会被Undo块信息U的内容替换。这两种情况都标志着这次事务操作的结束。而在事务操作结束之前,任何涉及数据块D的读操作都会命中Undo块信息U,而不是数据块D。这种方式能够在事务的一致性、回滚速度等方面实现极好的平衡。不过我们也可以清楚地看到,一个数据块的I/O操作实际上产生了若干个数据块的I/O操作,而且这里还没有讨论数据块D涉及的索引块对应的改动操作及锁机制,这些操作对一个OLAP环境来说基本上是不需要的。如果发生了,就意味着极大的I/O开销。OLAP环境中的更新操作一般情况下都是整片数据的删改问题,所以完全没有必要做基于记录层的事务,直接使用文件会使开销更小。
1700509368
1700509369
在Hadoop的HDFS中写一个文件(就像刚刚用HiveQL做LOAD命令那样),会引发对一个文件的复制操作。这个过程是一个轻型的复制过程,如图13-7所示。
1700509370
[
上一页 ]
[ :1.700509321e+09 ]
[
下一页 ]