关于go:近期Psql相关业务的收获agg函数对于null值的处理-arrayagg-Unmarshal的性能消耗和工作原理

47次阅读

共计 2203 个字符,预计需要花费 6 分钟才能阅读完成。

【case 1】
我的项目背景:
须要返回一些 GC 的统计数据。相干数据存在 frame 这张表内,表中的数据一行就是一帧的数据,能够了解为记录了这一帧内的性能信息。与需要相干的 col 是 GcChartSample,是一个 json 类型的数据,外面存的是该帧触发的各个品种的 GC 的大小,没有触发的 GC 的字段将不会列在这个 GC 中。例如:{“Internal”:252,”Other”:192,”Scripts”:7832},就是 InternalGC 是 252 字节,OtherGC 是 192 字节,ScriptsGC 是 7832 字节。
求:各类 GC 的无效帧均值(即:非 0 帧的均值)和最大值

我的第一版解法:
将区间内的所有帧的 GcChartSample 字段取出放入 go 中,在 go 中进行解决。即:先开一个 gcLineMap 记录所有呈现过的 GC 品种,而后再依据 gcLineMap 建设 gcItemArray,分类 push 非 0 的 GC 值,最初依据各个数组算出统计数据。

弱化局部需要后,mentor 举荐的解法:
用户在查看性能报告的时候,通常只会关注局部 GC 的值,例如:ScriptsGC,RenderingGC 等。因而,并不一定要求出所有 GC 的统计。并且 sql 善于做统计的操作。将统计的工作放在 sql 里做,可能缩小 IO。
因而,sql 批改如下:

select sum(cast(GcChartSample ->> 'Scripts' as Integer)) as ScriptsGCMax, round(count(cast(GcChartSample ->> 'Scripts' as Integer)), 2) as ScriptsGCMean,
       max(cast(GcChartSample ->> 'Rendering' as Integer)) as RenderingGCMax, round(avg(cast(GcChartSample ->> 'Rendering' as Integer)), 2) as RenderingGCMean,
       max(cast(GcChartSample ->> 'GUI' as Integer)) as GUIGCMax, round(avg(cast(GcChartSample ->> 'GUI' as Integer)), 2) as GUIGCMean,
       max(cast(GcChartSample ->> 'Animation' as Integer)) as AnimationGCMax, round(avg(cast(GcChartSample ->> 'Animation' as Integer)), 2) as AnimationGCMean
from upa.frame where partitionkey = 5;

起初放心,应用 sql 里的 avg 操作只能返回均值,无奈返回无效帧均值。然而,翻阅 sql 文档后发现,sum 会主动疏忽值为 null 的字段。

psql agg 操作总结如下:
AVG

SELECT AVG(amount)::numeric(10,2) FROM payment; //To make the output more readable
SELECT AVG(DISTINCT amount)::numeric(10,2) FROM payment; //The following query returns the average payment made by customers. Because we use DISTINCT, PostgreSQL only takes unique amounts and calculates the average.

COUNT

 将列名作为参数,失去 NULL 之外的数据行数
将星号作为参数,失去所有数据的行数 (蕴含 NULL)。

SUM

 对于列外面数据有 NULL 的,也是会当时去掉 NULL 再计算。

【case 2】
翻阅组内我的项目的时候发现,psql 中含有 array_agg 操作的,通常都不会在 go 端做解决,而是以 string 的形式接管,传递给前端解析成 json 进行操作。

学习笔记:
PostgreSQL array_agg() 函数是一个聚合函数,它返回一个蕴含了一个分组中的所有的值的组成的数组。

【case 3】
我的项目背景:
在做一个需要的时候,我将一个某个 sql 的返回值用 string 接到后,进行了 Unmarshal 操作,mentor 提醒说最好寻找一下优化的办法,因为 Unmarshal 操作要一个一个的对,比拟伤性能。

学习笔记:

  • Unmarshal 将 json 字符串解码到相应的数据结构。
  • json 字符串解析时,须要一个“接管体”承受解析后的数据,且 Unmarshal 时接管体必须传递指针。
  • 解析时,接管体可自行定义。json 串中的 key 主动在接管体中寻找匹配的项进行赋值。
  • 匹配规定:先查找与 key 一样的 json 标签,找到则赋值给该标签对应的变量;没有 json 标签的,就从上往下顺次查找变量名与 key 一样的变量,或者变量名疏忽大小写后与 key 一样的变量,第一个匹配的就赋值,前面就算有匹配的也疏忽(变量可导出,首字母大写)。
  • 当接管体中存在 json 串中匹配不了的项时,解析会主动疏忽该项,该项仍保留原值。
  • json 解析后,json 串中 value,只有是 ” 简略数据 ”,都会依照默认的类型赋值。
  • 简略数据:是指不能再进行二次 json 解析的数据,例如 name
  • 复合数据:是可进行二次甚至屡次 json 解析的,因为它的 value 也是个可被解析的独立 json

正文完
 0