24
润乾软件出品 并行取数提升报表性能 润乾 RAQSOFT

并行取数提升报表性能 - img.raqsoft.com.cnimg.raqsoft.com.cn/file/2019/10/30448699ae07489fb... · 数据库的JDBC到底有多慢? 【测试用例】 从3000万行,8列的customer表(文本大小4.9GB),分别从Oracle和MySQL中取数测试

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

  • 润乾软件出品

    并行取数提升报表性能润乾RAQSOFT

  • 背景

    有时候我们发现,数据库的负担一点也不重而且 SQL 很简单,但报

    表性能却很低

    分析后发现,性能瓶颈主要在 JDBC 上

    数据库JDBC效率影响报表性能

  • 数据库的JDBC到底有多慢?

    【测试用例】从3000万行,8列的customer表(文本大小4.9GB),分别从Oracle和MySQL中取数测试

    第一次 第二次 每秒行数

    Oracle 293 281 106000

    MySQL 518 381 79000

    测试结果(时间单位:秒)

    硬件环境:2个Intel2670 CPU,主频2.6G,共16核,内存64G,SSD硬盘

    3000万行的表要读 5分钟 !!! OMG

  • 如何加速?

    通过并行取数加速读取效率,利用多CPU能力

    但是,JAVA实现并行程序太难(要考虑资源共

    享冲突等麻烦事务)

    有没有简单的办法? DB

  • 润乾报表解决方案

    呈现模块 动态并发控制 日志服务展现模板编辑器

    缓存同步

    计算模块计算脚本脚本数据集

    并行取数

    参数查询 静态报表 导出 打印

    DB/DW FileSystem HDFS 其他数据源

    数据源

    引入计算模块,实施并行取数,提升报表性能

  • 并行数设置

    并行数是指在润乾报表中使用多线程并行取数,需要事先配置适

    合的并行数量

    如果不配置,即使使用并行计算脚本也无法并行取数

    注意并行配置

  • 并行数设置

    报表设计器IDE中,工具-选项-集算器选项:

    应用中,修改raqsoftConfig.xml中parallelNum值:

    4

  • 并行数应该设置多大?

    情况一:

    并行数≤CPU核数

    情况二:

    并行数远大于CPU核数

    通常并行程序的并行数量建议不要超过

    CPU核数,避免CPU线程切换影响性能

    将任务数设置到远大于CPU核数,可以设

    置为CPU核数的倍数个,这样多CPU负载

    也可以达到动态平衡

  • 说明

    润乾报表在计算模块中提供了多线程任务动态平衡机制,当任务数大于并行

    数配置时,报表会自动为计算结束的线程分配下一个任务,这时可以保证某

    个线程会多跑几个小任务,另一个线程只跑少量大任务,达到总体平衡,而

    不必拘泥于必须把数据量平均分配

    灵活性

  • 单表并行

    如何分段?

    a.有索引分段

    b.无索引分段

    多表并行

    并行取数与关联计算

    举例

  • 例1:利用索引字段分段并行

    均匀分段:单表并行取数前,需要进行数据分段,要保证每个分段的数据相对均匀

    利用索引可以加快分段数据定位,快速实施并行取数

    举例1 并行查询指定时间范围的订单数据

  • 例1:报表实现

    新建报表,使用脚本数据集:

  • 有效利用索引

    A B C

    1 =connect(“demo")

    2=A1.query(“select min(订单ID) 最小ID,max(订单ID) 最大ID from order)

    =b=A2.最小ID =e=A2.最大ID

    3 =p=4 /并行数 =range(b,e+1,p)

    4 =C3.to(,p) /分段参数初值

    5 =C3.to(2,) /分段参数终值

    6 fork A4,A5 =connect(“demo")

    7=B7.query@x(“select * from order where订单ID>=? and订单ID

  • 关于fork

    在润乾报表计算模块(脚本数据集)中,通过fork语句可以启动多个线程实

    施并行计算,同时还提供了多种merge函数可以很方便合并并行结果

    计算任务

    fork

    线程1

    线程2

    线程3

    线程4

    结果合并

  • 注意

    需要注意数据库连接必须在并行线程中建立,以便为多线程分别使用,

    若共用一个连接无法起到加速取数的效果,数据库会自动把同一连接

    上的多个请求改为串行执行。因此只有当数据库负担不重,有足够多

    连接可用时才可以使用并行取数提升性能

    注意事项

  • 例1:报表实现

    设计报表模板,编辑表达式

    基于脚本数据集ds1准备的结果集,采用列表方式呈现

  • 性能比较

    比较使用并行前后的报表性能(仅比较数据集计算时间):

    14

    7

    0

    2

    4

    6

    8

    10

    12

    14

    16

    串行 4线程并行

    数据集计算时间(秒)

    在本地的PC上,通过4线程可以提速一倍

  • 例2:非索引字段分段

    如果数据库负担不重时,也可以基于非索引字段进行分段(如日期),相对

    JDBC取数时间,多次遍历库表时间也并不是很大

    好处:不需要事先查询数据库以确定起止段界

    举例2 并行查询指定时间范围的订单数据

  • 例2:报表实现

    新建报表,使用脚本数据集:

    这里不再计算订单范围,直接使用日期字段进行分段并行

    报表模板与例1相同,本例省略

  • 例3:多表并行取数

    有时,报表包含多数据集,此时仍然可以通过并行同时执行多条SQL语句进行取数,提升报表性能

    order

    orderID

    orderDate

    customerID

    eID

    customer

    customerID

    customerName

    area

    employee

    eID

    eName

    orderDetail

    orderID

    productID

    price

    quantity

    product

    productID

    productName

    type

    举例3 并行读取5个表数据,查询订单相关信息

  • 例3:报表实现(脚本数据集部分)

    A B C

    1 =connect(“demo")

    2 ="select * from order where orderDate>=date('"/begin/"') and orderDateod.switch(customerID,cus:customerID;eID,emp:eID)

    12 =detail.switch(orderID,order:orderID;productID,prod:productID)

    13=A12.new(orderID.customerID.customerName:cusName,orderID.orderID:orderID,orderID.eID.eName:empName,productID.productName:prod,price, quantity)

    新建报表,设置脚本数据集(为了查看方便仅列出脚本内容):

  • 例3:报表实现

    直接使用上述数据集,进行报表呈现

  • 性能比较

    比较使用并行前后的报表性能(仅比较数据集计算时间):

    14

    7

    0

    2

    4

    6

    8

    10

    12

    14

    16

    串行 4线程并行

    数据集计算时间(秒)

    在本地的PC上,通过4线程可以提速一倍

  • 总结

    润乾报表多线程并行的意义在于使用简单、成本低,相对JAVA复

    杂的多线程编程,润乾报表可以简单到几行脚本,当遇到多库和异

    构数据源场景时更有意义

    简单、低成本