Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

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

          SAP作为全球企业信息化的龙头软件企业,出于对该问题的考虑,在设计新一代内存数据库产品SAP HANA时,其初衷就是为了实现企业应用中OLTPOLAP系统的结合。在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区域的数据是行存储,而主存储区的数据是列存储,如果此时进行表查询,表关联之类的操作,由于存储格式的差异,数据库会在两片区域内寻找匹配加工数据,在columnrow engine之间不停切换,会对性能产生不利影响。所以在Delta区域中数据达到一定程度时,或者再某段频繁的OLTP操作结束之后,可以手工对表进行“Merge”:


merge delta of [table_name]

2.     多线程

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

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

     开启多线程有多种方式,可以在JDBCODBC开启多个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 volumelog volume都会有所增加。

4.     JDBC优化

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

    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-...,请勿用于任何商业用途。

1 Comment