在云计算环境下, 数据量的增长非常迅速, 数据量由GB级向TB、PB级上升, 传统的关系数据库已无法应对大数据量的存储和管理, 使得新型的NoSQL数据库得到了快速发展。主要的NoSQL数据库包括Google的BigTable [1]、Spanner [2], Amazon的Dynamo [3], Apache的Cassandra[4]等。这些非关系数据库很好地解决了大数据量的存储和管理问题, 提供了可扩展性和可用性。但是, 传统的金融业务, 除了要处理海量数据外, 还需要保证数据处理过程中事务的强一致性。Brewer的CAP理论指出, 任何分布式系统不可能同时满足一致性、可用性和分区容错性, 最多只能满足其中2项[5]。因此目前大多数的NoSQL数据库不支持事务的强一致性, 从而无法满足金融业务的需求。
Oceanbase是阿里巴巴所提出的一种融合NoSQL数据库架构和关系数据库特点的新型数据库架构[6], 不仅能支持跨行跨表事务的强一致性, 也能支持数据节点的可扩展性。该数据库是一个架构于MySQL数据库之上的开源数据库, 可支持SQL查询, 在应对金融业务上, 具有很大优势, 已经成为学术界和工业界关注的热点。
游标是传统关系数据库中一个十分重要的概念[7]。游标提供了一种对从表中检索出的数据进行操作的灵活手段, 就本质而言, 游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标总是与一条SQL查询语句相关联, 因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。当决定对结果集进行处理时, 必须声明一个指向该结果集的游标。在银行业务中, 对检索出的数据逐条处理是一个常用功能, 通常用游标来实现。例如, 计算2015年度所有帐户的利息额度, 需要首先获得该年度的所有帐户的存款额度, 然后根据当年的利率逐个计算每个帐户的利息, 最后将利息加入帐户总金额中。由于游标的结果大多存储在内存中, 并需要占用一定的内存空间来计算, 因此对于追求高效的NoSQL数据库而言, 大多数都不支持该功能。
Oceanbase虽然融合了关系数据库和NoSQL数据库的优点, 可以处理海量数据并支持关系接口, 但在游标的实现上, 仍未得到支持, 这对于当前具有大数据处理需求并关注事务强一致性的金融业务而言, 已成为极大的阻碍。
本文提出了一种面向海量分布式数据库的游标构造方法, 通过分析海量分布式数据库的架构和查询特点, 对于游标使用过程中的主要关键字:Declare、Open、Fetch、Close、Deallocate等, 分析了分布式数据库的SQL执行流程, 设计游标的语法树、逻辑计划和物理计划结构, 然后按照词法分析、语法分析、逻辑计划生成、物理计划生成、物理计划执行的流程完成游标执行流程。该方法已经在Oceanbase的0.4.2版本上进行了算法实现和实验验证, 实验结果表明, 该方法能实现分布式数据库的游标功能, 并且和商业数据库DB2的游标功能进行了比较, 在百万级的数据量测试中, 本文所提出的分布式数据库实现的游标功能优于商业数据库DB2的游标性能。
1 Oceanbase架构Oceanbase是典型的分布式数据库架构, 系统中包括4类服务器:主控服务器Root Server、更新服务器Updates Server、基线数据服务器Chunk Server和数据合并服务器Merge server。图 1是Oceanbase的物理架构图。
主控服务器Root Server负责服务器的管理以及系统的负载均衡; 更新服务器Updates Server用于保存每天的增删改的数据(增量数据), 执行写事务, 同时提供读服务。为了保证业务的可用性, 更新服务器采用了一主一备的结构, 写事务同时写入主备服务器, 主备服务器之间可以根据业务执行情况灵活切换。基线数据服务器Chunk Server负责存储基线数据并提供访问。为了提高系统可用性和数据安全性, 基线数据服务器保存了数据的多个副本在不同的Chunk Server上。当某台Chunk Server发生故障时, 系统会自动切换到其他副本所在基线服务器上继续工作。数据合并服务器Merge Server负责接受来自客户端的查询, 支持JDBC/ODBC协议, 用户发送的SQL语句在合并服务器上进行解析, 将解析结果发送给Chunk Server。Chunk Server将基线数据和增量数据合并后, 便得到查询结果, 并通过合并服务器返回给客户端。
Oceanbase的数据管理方式不同于其他的分布式数据库, 如HANA[8]、VoltDB[9]等。这些数据库采用统一的方式来管理增删改数据和只读数据。而Oceanbase将这2种数据分开, 只读数据(基线数据)采用分布式管理, 而增删改数据(增量数据)则放在内存统一管理。这是一种新型的分布式系统的设计模式, 其假设是尽管数据库中数据的总量很大, 但系统在某一段时间内(如一天)的增删改的数据总量并不大, 由于增量数据都在一台服务器上, 因此可以实现事务的强一致性, 而基线数据的分布式存储, 也可以实现数据的高可用性。
2 面向海量分布式数据库的游标构造方法和传统数据库的SQL执行过程类似, Oceanbase的SQL执行流程首先要经过词法分析和语法分析、其次将语法分析输出的语法树进行转换, 生成可以执行的物理计划, 最后由Merge Server执行计划, 分别向Chunk Server请求基线数据、向Update Server请求增量数据, 并将合并后的数据返回给客户端。分布式数据库和普通关系数据库的差别在于数据的分散存储和数据融合过程。传统的基于磁盘的关系数据库读取事务的操作是先从磁盘读出数据页, 取出所需要的内容, 然后根据用户SQL进行操作, 得到相应的结果; Oceanbase针对只读事务, 除了从分布式基线数据服务器的数据页取出所需要的内容外, 还要从更新服务器取得和该查询对应的修改增量并进行融合, 从而得到最新的查询结果。
由于Oceanbase并不支持游标功能, 因此上述分布式数据的读取、合并的过程都需要添加新的设计和数据结构。
本文在考虑上述分布式架构和SQL查询流程的基础上, 设计了一种完整的游标构造方法, 为游标常用的关键字构造了统一的语法树、逻辑计划和物理计划, 并设计了游标SQL的执行流程。实验结果表明, 该方法能够完成分布式数据库的游标功能, 并在大数据量查询时, 具有较优的查询性能。
2.1 语法树构建语法树是SQL语句经过词法和语法解析后生成的数据结构。根据不同的SQL语句, 所生成的语法树也有所不同。
为了设计游标的语法树, 我们首先需要分析游标的执行过程。游标多用于SELECT语句查询结果是多条记录, 需要将多条记录一次一条送主程序处理, 从而把对集合的操作转换为对单个记录的处理。通用的游标的使用步骤为:
① 说明游标, 用DECLARE语句定义游标。
② 打开游标, 用OPEN语句将定义的游标打开。打开游标实际上是执行相应的SELECT语句, 把查询结果取到缓冲区中。这时游标处于活动状态, 指针指向查询结果集中的第一条记录。
③ 使用游标读取数据, 通过循环执行FETCH语句逐条取出结果集中的行进行处理。
④ 关闭游标, 用CLOSE语句关闭游标, 释放结果集占用的缓冲区及其他资源。游标被关闭后, 就不再和原来的查询结果集相联系。但关闭的游标可以再次被打开, 与新的查询结果相联系。
⑤ 用DEALLOCATE释放游标。
因此, 游标涉及的关键字包括:Declare、Open、Fetch、Close、Deallocate, 游标的名称是所有节点共通的部分, 用来区分不同的游标。此外, Declare语句中要包含Select查询部分, 因此需要有第二个子节点, Fetch语句中要输入获取数据的方向, 例如从第一条记录开始还是从最后一条记录开始读取数据。游标语法树节点的主要数据结构设计如图 2所示:
作为游标共通的语法树, 其数据结构分为必选节点和可选节点, 必选节点为childen-[0], 是游标的每个关键字必须构造的节点, 主要是存储游标名称。可选节点是为childen-[1], 只有Declare和Fetch关键字需要构造, Declare用来构造语句中所包含的Select查询的相关信息。Fetch用来存储取得数据方向的信息, 例如是正向检索还是反向检索。
2.2 逻辑计划构建逻辑计划旨在根据语法树生成对应的数据结构, 将SQL语句中所涉及到的表、字段、表达式等解析出来并判断有效性, 但逻辑计划不可执行。在一个逻辑计划中, 每一个查询有一个唯一标识query-id与之对应且每一张表有一个唯一的标识tid, 每一个列有一个唯一的标识cid, 每一个表达式有一个唯一的标识eid。游标中, 本文对逻辑计划设计的主要数据结构如图 3所示。
游标逻辑计划的构造也包含必选节点和可选节点。必选节点包含了所有游标关键字所必须构造的节点信息, 包括查询标识query-id、游标名称cursor-name、逻辑计划类型stmt-type。可选节点主要针对declare和fetch关键字设计。对于这2个关键字时, 逻辑计划中还要保存declare查询标识declare-query-id和数据获取方向fetch-direction。对于declare, 还需要保持其中查询语句的相关信息select-stmt, 即包含Select关键字的查询语句。
2.3 物理计划构建物理计划是一系列数据操作的有序集合, 由逻辑计划解析而成, 是可执行的最终数据结构。本文对游标物理计划设计的数据结构如图 4所示。
游标的物理计划, 在原有物理计划ObPhysicalPlan的基础上, 进行改造而得, 其中cursor-phyOp代表游标的物理操作符, 根据关键字的不同会有所变化, 可选节点信息是针对declare节点中所包含的Select查询语句的物理操作符信息, 由于Select物理操作符的设计在Oceanbase中已经完成, 因此不加以展开。
2.4 游标执行流程设计游标的执行流程类似于其他SQL的执行流程, 构造完游标各个阶段的数据结构之后, 可以采用图 5所示的方式完成游标功能的执行。
游标中Declare、Open、Fetch、Close、Deallocate语句都是新加的SQL语句。其中, 除Declare语句不执行物理计划外, 本文其余的语句都按照图 5的方式完成物理计划的执行。
Declare语句是存储Select语句的物理计划和游标的名字。
Open语句通过游标名找到与之对应的Select语句物理计划并执行, 缓存Select语句用于处理结果集。对于结果集的缓存方式, 考虑了内排和外排(内存放不下时)2种情况:当内存可以放下全部数据时, 排序只有一路; 当内存不能放下全部数据时, 排序会采用多路, 将中间结果刷到外存上。
Fetch语句通过游标名找到与之相关的结果集, 用单向单行方式取结果集中的一行数据。
Close语句通过游标名找到与之相关的结果集后, 关闭游标并释放结果集。
Deallocate语句通过游标名找到与之相关的物理计划后, 删除物理计划, 释放游标。
游标根据Oceanbase的分布式架构实现, 因此在执行过程中, Select查询部分依然要遵循先查Chunk Server, 获取基线数据, 再查Update Server, 获得增量数据, 最后将两者合并之后存入内存, 根据游标的指针进行逐条读取。由于游标的定义仅仅是对游标命名, 因此在该阶段, Declare语句中所包含的Select查询并未实际执行, 只是保存在内存中。待执行Open语句执行时, 才进行数据的获取和融合; 合并后的数据放入缓存, 等待Fectch语句的逐条读取和操作。当游标使用完毕, 可以用Close语句进行关闭、或用Deallocate进行删除。
3 实验与分析为了测试上述方法所构造的游标在大数据量查询时的性能, 我们在Oceanbase 0.4.2的版本上实现了游标功能, 并和商业数据库DB2, 在百万级数据量的查询性能进行了比较。下面是游标性能测试的实验方案。
1) 实验环境:Oceanbase单服务器部署。服务器由1T硬盘, 16G内存, 16核CPU, 一块网卡组成。服务器操作系统是Red Hat6.2, 内核是2.6.32-220.el6.x86-64。
2) 实验目的:测试Oceanbase和DB2的游标功能在100万级数据量的表中取数据的性能差异。表中有100万数据, 结果集为各种数据量(1万到80万), Fetch完所有数据, 测试open和fetch语句取全部结果集的执行时间。
3) 实验的SQL语句:测试SQL语句模板如下所示:
(1) declare cursor csr1 for select * from test-100w where id < n
(2) open csr1
(3) fetch csr1
(4) close csr1
实验结果:表 1所列的是Oceanbase和DB测试结果的对比。
表 1结果表明:随着Fetch数据量的增加, Oceanbase和DB2的游标获取数据的时间均会增加, 但Oceanbase的所增加的时间远远小于DB2, 在80万数据时, 仅需要6 min左右, 而DB2则需要568 min左右。Oceanbase的游标速度比DB2要快81倍左右, 查询速度更快, 性能优于DB2。这也体现了分布式数据库在大数据量查询时的优势。
4 结论在云计算环境下, 随着数据量的不断增长, 海量分布式数据库已经成为目前的主流应用。由于大多数分布式数据库采用NoSQL架构, 并不支持SQL或仅支持简单的查询语句, 故对于大型的金融企业而言, 不仅要求数据库能处理大数据, 还要支持关系查询, 并保证数据的强一致性。Oceanbase满足了上述需求, 但对于金融企业中常用的游标操作则不支持, 这阻碍了该数据库在金融企业的进一步应用。本文提出了一种面向海量分布式数据库的游标构造方法, 可以实现分布式数据库的游标功能。首先构造了游标关键字共通的语法树、逻辑计划和物理计划, 随后设计了游标整体的执行流程。该方法补充了分布式关系数据库中游标设计的不足, 并提高了游标的查询性能。本文所提出的游标构造方法, 已在银行业务中得到成功应用, 实践证明, 在大数据量的查询过程中, 本文所提出的方法中游标查询速度优于商业数据库DB2的游标查询速度。
[1] | Chang F, Dean J, Ghemawat S, et al. Bigtable: A Distributed Storage System for Structured Data[J]. ACM Trans on Computer Systems, 2008, 26(2): 4. |
[2] | Corbett J C, Dean J, Epstein M, et al. Spanner: Google's Globally Distributed Database[J]. ACM Trans on Computer Systems, 2013, 31(3): 8. |
[3] | DeCandia G, Hastorun D, Jampani M, et al. Dynamo: Amazon's Highly Available Key-Value Store[J]. ACM SIGOPS Operating Systems Principles, 2007, 41(6): 205-220. DOI:10.1145/1323293 |
[4] | Lakshman A, Malik P. Cassandra: A Decentralized Structured Storage System[J]. ACM SIGOPS Operating Systems Review, 2010, 44(2): 35-40. DOI:10.1145/1773912 |
[5] | Brewer E A. Towards Robust Distributed Systems[C]//Nineteenth ACM Symposium on Principles of Distributed Computing, Portland, USA, 2000:16-19 |
[6] |
阳振坤. OceanBase关系数据库架构[J]. 华东师范大学学报:自然科学版, 2014(5): 141-148.
Yang Zhenkun. The Architecture of Oceanbase Relational Database System[J]. Journal of East China Normal University(Natural Science), 2014(5): 141-148. (in Chinese) |
[7] |
孟德欣. Oracle. 9i数据库技术[M]. 北京: 清华大学出版社, 2004.
Meng Dexin. Oracle. 9i Database Techniques[M]. Beijing: Tsinghua Press, 2004. (in Chinese) |
[8] | Lee J, Kwon Y S, Farber F, et al. SAP HANA Distributed In-Memory Database System: Transaction, Session, and Metadata Management[C]//2013 IEEE 29th International Conference on Data Engineering, 2013: 1165-1173 |
[9] | Stonebraker M, Weisberg A. The VoltDB Main Memory DBMS[J]. IEEE Trans on Data Eng Bull, 2013, 36(2): 21-27. |