大量报表的生成优化办法

前言

一个页面,加载耗时1.3分钟,分析后发现用的O/RM,我记得12306以前爆是因为用的hibernate,而且没用好。

O/RM有各种硬伤,但总是有优化办法。我改进后测试1秒。

痛点

澳大利亚很多政府/企业财年结束(6月30日)便需要进行一些年度操作,譬如给客户发送年度报告等等。

澳大利亚最大的养老金管理也不例外,需要给数百万用户发送一个流水账单(PDF文件格式),根据多年来的观察和官方的说明,一般需要等到9月底到10月初,这意味着需要起码2个月来处理。

分析

简单计算,意味着顺序处理的话,大概每秒完成一个客户,听起来不算慢。

大家会觉得,一年的流水,多则几百条记录,取出来0.4秒,生成PDF是0.5秒,发送0.1秒,那相当合理。

在这个系列操作中,单个业务的瓶颈可能是:

  • 数据获取/计算
  • PDF生成
  • Email发送

优化

最佳的优化,彻底理解业务逻辑后作出相应的改动。在没有理解业务逻辑之前,我们一般提供效率的做法可能有:

  • 分而治之:多个服务器并行操作,每个负责某个用户组,譬如如果有10台机器,那机器1可以处理10%,如此
  • 队列异步:数据获取/计算、生成PDF和Email都分开队列,异步处理,这样每一步的操作不会因为其中一部堵塞后续的操作
  • 内存操作:PDF生成无需写入磁盘再作为附件发送出去
  • 外部资源:邮件发送可以使用第三方的支持异步的服务,譬如Sendgrid,除了独特的功能之外,我们需要的是无阻塞的异步高性能操作

关于数据获取/计算,如果要做优化,可以在设计上做一些改动,譬如加入每月统计,这样到财年末的时候只需要统计过去12个月的月统计便可。而且这些流水如账本那样,只会append only,不会对现有记录进行改动,所以无需考虑重新统计。

另外,单数据库会是性能(还有安全)瓶颈,完全可以把流水/统计数据放到多节点NoSQL里面,取的时候性能优于关系型数据库。

 

当然,还有一些更高级、复杂的优化实践,有兴趣的同学们可以根据右边二维码加我的微信。

 

想知道为什么我这么多年来能掌握那么多种技术,不仅仅是广度,还有深度,达到我所说的“爆栈”吗?

在《爆栈之旅》,我根据大家都实际情况、水平、方向等规划职业路径,手把手带你做实战的项目,用最高效的办法达到你想要的高度。

爆栈之旅

是否想技术水平快速提升?是否希望快速成为公司的技术骨干?

核心价值
  • 把我这10多年来所学到的知识、总结的经验、吸取的教训分享出来
  • 针对不同的学生量身定制规划学习成长路线、1对1个人指导、代码审阅等
  • 解答各种技术问题
  • 为公司提供技术解决方案

请查看本站右边的信息联系我。

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。

爆栈思想 – 怎么样才算是某个领域的专家

我们发现,很多简历充斥着各种“精通”,尽管刚毕业不久,没有多少实际项目经验。

 

究竟怎么样才算是某个领域的专家呢?

 

应该分几方面看:
  • 技术深度
  • 影响力
  • 对社区的反哺/贡献
譬如数据库存储这块,拿SQL Server做例子,应该掌握以下技术的原理、解决办法和最佳实践:
  • 数据类型/对象
    • 各种数据类型的转换优先级、差异
      • 看似简单,举2个例子:
        • SELECT 1 + ‘+’ + 1
        • 4种不同的临时表/表类型差异和最佳实践
  • 访问
    • 各种DDL/DML/DCL/TCL的最佳实践
  • 内核机制
    • 调度器
    • 各种hint
      • 升级、优先级和差异
      • 堵塞
      • 死锁
    • 等待/延迟
    • IO Stall
    • 进程/请求/任务/连接
    • 缓存/缓冲
  • 最大限制与版本差异
    • 各种级别/方面的最大/最小限制
    • 不同版本的差异
    • 不同版本的新特性、失效特性
  • 深入排错
    • 错误的级别和哪些会在客户端触发
    • 排错的多种方式
  • 调优
    • 表、列设计的最佳实践
    • 索引、扫描、各种Lookup、Bookmark
      • 各种类型的索引的差异
      • 性能相差数万倍的设计
      • 索引管理最佳实践
    • 执行计划
      • 如何找到性能瓶颈
      • 编译、损坏与修复
      • 如何强制刷新(多种方法和副作用)
    • 不同方法的性能巨大差异
      • 譬如COALESCE vs FOR XML vs STRING_AGG
    • 利用多核的最佳实践
    • 数据库/日志文件切分、存储的最佳实践
    • 数据库/日志备份/恢复的最佳实践
    • 内存调度最佳实践
    • 内联
    • 各种trace flags
  • 海量数据处理
    • 高效分库分表
      • 各种切分的优缺点
    • 如何实现大量数据的导入和导出
  • 安全和访问控制
    • 如何实现实例、数据库、表、行、列多级访问控制
    • 如何防止注入和入侵
    • 跨库访问的最佳实践
  • 审计和记录
    • 审计的最佳实践
    • 如何高效实现修改操作记录
  • 容灾、高可用最佳实践
    • AlwaysOn / HAG
    • 如何fail over
    • 备份的多种方式、差异和最佳实践
  • 扩展
    • SQL CLR
  • 管理/自动化
    • 任务
    • DMV
    • DBCC
  • BI
    • SSIS
    • SSAS
    • SSRS
如果详细写下来,这会是一本《SQL Server专家》。

 

关于影响力、对社区的反哺和贡献,这主要是看是否参与社区的讨论/问题解决、代码贡献等。

 

 

想知道为什么我这么多年来能掌握那么多种技术,不仅仅是广度,还有深度,达到我所说的“爆栈”吗?

在《爆栈之旅》,我根据大家都实际情况、水平、方向等规划职业路径,手把手带你做实战的项目,用最高效的办法达到你想要的高度。

爆栈之旅

是否想技术水平快速提升?是否希望快速成为公司的技术骨干?

核心价值
  • 把我这10多年来所学到的知识、总结的经验、吸取的教训分享出来
  • 针对不同的学生量身定制规划学习成长路线、1对1个人指导、代码审阅等
  • 解答各种技术问题
  • 为公司提供技术解决方案

请查看本站右边的信息联系我。

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。

爆栈思想 – 数据库“状态”字段如何设计

前言

之前在文章《学员问答精选 – 1 – 数据库表拆分》中提及过一个数据库的设计问题。今天,微博上的@火丁日记 说:

表里有一个 status 字段,用来表示数据的状态,比如订单的已付款,已关闭等。以前我习惯把它定义为 INT 类型,但是慢慢的,我就记不清楚 1,2,3 到底指的是什么意思了,也想过用 ENUM 类型,但是不方便扩展,最后,我觉得直接用 VARCHAR 类型算了,去它的三范式。

百家争鸣

  • 一些网友赞同使用varchar
  • 一些还是觉得应该enum
  • 一些觉得最原始的int是最好的
  • 一些觉得要用字典表

各种考量

其实,一个字段类型的考量,主要包括:

  • 准确性/精确性:必须能满足业务需求,不能丢数据,溢出等
  • 性能:一般来说,int的运算比varchar要快
  • 空间:尽可能占用最少的空间,一条记录浪费1字节,10亿记录就浪费1GB空间了
  • 辅助性:譬如方便功能上的排序、方便开发人员记忆等

如果要为开发人员着想:

  • 数据库里,表的字段可以添加描述,譬如0: Pending, 1. Paid, 2: Processing, 3: Delivered, 4: Cancelled
  • 如果不满足,那可以用char(1),26个字符足够表达各种状态了吧?不够就char(2),再不行就char(3),主要是省空间。为什么不用varchar(n)而用char(固定数值)?因为varchar(n)要运算做各种trimming,起码在SQL Server里,譬如len()就是后面空格去掉后的长度,和datalength()不一样。这个一般是单词的首字母,记起来比int舒服些。我发现一些公司就是这样做的。

如果要追求节省空间,完全可以用tinyint甚至varbinary,毕竟1个字节有8位,一般订单也就那么几个状态吧?

首先,如果用varchar,那么要考虑:

  • 你这个状态的值,是放英文还是中文?你的产品是否全球化的?
  • 如果是放英文,那你还是需要本地化。
  • 而且,既然要本地化,就没必要放完整的单词,char(1)便可,原因参考上面。

如果使用int,那么要考虑:界面文本显示,开发人员友好。

如果要考虑界面显示如排序等,一般来说,界面需要先根据条件过滤出来某种状态,但是,如果你的业务逻辑就是要同时显示多种状态的数据,这要考虑目标数据只是已经在界面的,还是在数据库的:

  • 界面:那数据库的类型还是最精简的varbinary(1),在界面对值进行解释然后根据解释出来的规则进行排序

当然,有些业务系统会使用字典表,相当于外键,如果返回结果的时候就join,这里会比case xx when 1 then ‘某状态’ 的效率要差些,而且字典表还是需要做语言本地化的。

总结

其实,不管用哪种方案,都没有完美的,还是应该具体业务需求来。

 

爆栈之旅

是否想技术水平快速提升?是否希望快速成为公司的技术骨干?

核心价值
  • 把我这10多年来所学到的知识、总结的经验、吸取的教训分享出来
  • 针对不同的学生量身定制规划学习成长路线、1对1个人指导、代码审阅等
  • 解答各种技术问题
  • 为公司提供技术解决方案

请查看本站右边的信息联系我。

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。