添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

目前市面上的数据库产品,由于受限于自身设计架构,在实现 OLTP Online Transaction Processing, 联机交易处理)和 OLAP Online Analytical Processing, 联机分析处理)上都存在一定的倾向性。从性能角度考虑,必须舍弃一方以达到另一方的良好展现,数据存在于不同数据库中,这使得大部分企业的交易系统和分析系统都是独立存在的,给企业的信息化造成一定的阻碍。

SAP 作为全球企业信息化的龙头软件企业,出于对该问题的考虑,在设计新一代内存数据库产品 SAP HANA 时,其初衷就是为了实现企业应用中 OLTP OLAP 系统的结合。 在SAP HANA 中引入了“列存储”表的概念,这种存储方式的表与传统的“行存储”表的区别在于:“行存储” 表的每行记录在内存地址中是连续存放的;而“列存储”表的每一列数据在内存中是连续存放的。这种区别造成了 “列存储”表在 OLAP 上,例如针对某个字段进行聚合函数操作时候具有非常好的性能,而在进行 OLTP 上,则因为需要实时调整内存中的数据存放结构,所以在性能上会有所影响。

为了解决“列存储”表在 OLTP 上的性能问题, SAP HANA 给每一张表都开辟了名为“ Delta ”的区域,与表的主存储区相对应。该区域内部是行式存储的, OLTP 的更新数据都会先存放到该区域,因此会比直接写入到列存储区上性能要好。在达到某些条件的时候, Delta 区域会和主存储区的数据进行合并的操作,将行式的数据转成列式的数据存储。以上所述的 Delta 区域是 SAP HANA 数据库的自身架构设计,可以一定程度上解决与完全的行存储表在 OLTP 性能上的差距。而从应用角度出发,还是有很多的 设计方法可以进一步提升“列存储” 表的 OLTP 性能。

1. 关闭表的自动 Delta Merge 功能

前面提到,“列存储”表在 Delta 区域中的数据达到一定程度时,会和主存储区做“ Merge ”的操作。在进行这种操作的时候,会将目前的 Delta 区域锁定,即任何的 OLTP 操作都会被阻塞住,不能再向该区域进行数据更新。在“列存储” 表建立的时候,“ Delta Merge ”是自动打开的,因此很难预料到在何时会进行“ Merge ”操作,如果在进行“ Merge ”操作时有很频繁的 OLTP 操作,会对性能产生巨大的影响。

这里,推荐的做法是,在常用的会进行 OLTP 操作的表上将自动“ Delta Merge ”功能关闭。可以用如下的 sql 命令来实现:


     alter table [table_name] disable automerge

当然,也可以用如下的命令来开启自动“ Merge ”功能:

alter table [table_name] enable automerge

之后数据库会定时查看 Delta 区域是否满足 merge 条件,以决定在后续的某个时间点进行 merge 操作。

由于 Delta 区域的数据是行存储,而主存储区的数据是列存储,如果此时进行表查询,表关联之类的操作,由于存储格式的差异,数据库会在两片区域内寻找匹配加工数据,在 column row engine 之间不停切换,会对性能产生不利影响。所以在 Delta 区域中数据达到一定程度时,或者再某段频繁的 OLTP 操作结束之后,可以手工对表进行“ Merge ”:


merge delta of [table_name]

2. 多线程

由于 OLTP 大部分都是比较轻量的数据库级操作,消耗的时间基本都是秒级以下。因此在单线程情况下,性能的提升十分有限。在 insert/update/delete 某条记录的时候,数据库对于该表只会有行级锁,由于不同记录之间没有依赖性,所以利用多线程并行不会有堵塞的情况发生操作,反而会减少 CPU 等待时间以及数据库响应时间,这会对性能有十分显著的提高。

一般来说,随着开启的线程数量的增加,性能会有线性的提升。但受到数据库自身以及数据库服务器的配置的局限性,到后面性能提升的效果会逐渐减弱,直至最后趋于平衡。

开启多线程有多种方式,可以在 JDBC ODBC 开启多个 connection ,也可以利用 SAP HANA 自带的 hdbsql 命令,通过 shell 脚本异步调用多个 hdbsql 命令,达到并行的效果。

针对于单条记录的 OLTP 操作,只需要开启多个数据库的连接,就可以达到并行的目的。但可能还存在需要批量插入很大数据量的操作,例如 insert into [table1] select * from [table2], table2 的数据量很大,如果直接使用该语句只能够用到单个线程。这时候必须要从数据本身入手,看是否有某些字段可以进行物理拆分。例如如果表中有 ID 的数字字段,可以通过 ID 的某位数字 [0-9] 进行物理拆分,将大的 insert 操作拆分成 insert into [table1] select * from [table2] where ID like ‘%[0-9]’ 这样的多条 insert 语句来执行,此时多条语句就可以充分利用到多线程了,此时性能也会有较为显著的提高。

3. 表分区

SAP HANA 中可以对“列”存储表进行分区( partition )划分。建立表分区有几个优势:

    1. 数据分布在各个分区内,可以充分利用多线程,各线程负责从某一个分区内处理数据,达到并行效果。
    2. 可以针对业务场景划分表。例如将若干年的销售数据通过月份进行分区,那么如果需要进行某月销售记录的分析时,只需要从某个分区取数据,减少取记录的数据量。
    3. OLTP 更新的数据散落在不同分区,避免对同一块数据区域频繁操作。

SAP HANA 提供了三种分区方式: Hash 分区、 Range 分区以及 Roundrobin 分区。前两者是针对某个或联合字段进行分区,区别在于 hash 分区是对字段的哈希值进行分区,而 range 分区则是定义了字段的取值范围。一般来说,如果涉及到年月日时间字段的数据,可以考虑通过 Range 分区,将数据划分到月或日的区间内;如果例如客户 ID 号这样的字段数据,可以考虑 Hash 分区,在真实系统中, ID 号这样的自增数字字段,按照 Hash 值划分在可以达到较好的均匀分布。 Roundrobin 则是针对整张表记录进行随机划分,将数据按记录条数均匀分配到分区之中。

表分区一般会和多线程结合起来使用,以达到最佳的性能。不仅仅是事务性操作可以分多线程来处理; delta merge 的操作也可以针对于某一个表分区,因此也可以利用多线程并行来 merge 表:


          merge delta of [table_name] part [partid]

当然,建立分区也会带来一定的代价。存储表数据所需要的 data volume log volume 都会有所增加。

4. JDBC 优化

SAP HANA 提供了 ODBC JDBC MDX 等数据驱动方式,供外部程序调用。其中 MDX 主要用于模型数据的获取展现,对于 OLTP 操作来说,主流的数据驱动方式还是 ODBC JDBC 。这里主要以 JDBC 为例谈一谈如何提高 SAP HANA OLTP 的性能。

1. 关闭自动提交

自动提交模式每次执行 SQL 语句都将执行自己的事务,并且在执行结束提交。关闭之后可以将一组数据库操作放在一个事务中。

2. 增加 commit 的数据条数

在事务性操作过程中,每一次提交都会产生一定的数据库开销。在实际场景允许情况下,尽可能减少 commit 的次数会减少无谓的开销,从一定程度上提升性能。

3. 采用 batch 方式提交

JDBC 中,可以定义 batch 的提交方式 , 这种方式可以减少数据库数据传输的往返次数,从而提高性能。


conn = DriverManager.getConnection (connection, username, password);
               stmt = conn.createStatement();
               stmt.addBatch(sql);
               stmt.executeBatch();



想获取更多 SAP HANA 学习资料或有任何疑问,请关注新浪微博 @HANAGeek !我们欢迎你的加入!

转载本文章请注明作者和出处 http://scn.sap.com/community/chinese/hana/blog/2014/04/15/%E6%B5%85%E8%B0%88sap-hana%E4%B8%ADcolumn-... ,请勿用于任何商业用途。