日常烦恼
作为工程师,我们在日常工作中,经常会遇到数据单位或时间单位不一致的日志或者指标数据,很多公共软件也都是将指标或数据以方便阅读的单位形式进行输出和展示的。
这类数据虽然阅读方便,但是一旦需要进行汇总分析或者进行比较排序时,往往需要将数据的单位大小进行归一化,然后再进行后续处理,这个工作本身不难但却非常繁琐,常常让我们感觉到蹩手蹩脚,影响工作效率。
一个例子
例如,下面是一个具体的实例,左图是java gc原生日志,右图是经过数据切割后的指标数据。
现在,我们需要分析每次垃圾回收后的jvm内存占比,计算公式:heap_used_after / heap_capacity_after,但是heap_used_after是M为单位,而heap_capacity_after是G为单位,为此,我们需要写出如下繁琐的SQL:
heap_used_after | select (cast(replace(heap_used_after, 'M') as double) * 1024 * 1024) / (cast(replace(heap_capacity_after, 'G') as double) * 1024 * 1024 * 1024)
事实上,事情可能还并非如此简单,heap_used_after的单位可能是M,可能是K,也可能是G,因此我们需要针对每种情况分别进行转换,于是,SQL变得更加冗长而繁琐:
heap_used_after | select ( CASE WHEN regexp_like(heap_used_after, '\d+\.?\d*B$') then cast(replace(heap_used_after, 'B') as double) WHEN regexp_like(heap_used_after, '\d+\.?\d*K$') then cast(replace(heap_used_after, 'K') as double) * 1024 WHEN regexp_like(heap_used_after, '\d+\.?\d*M$') then cast(replace(heap_used_after, 'M') as double) * 1024 * 1024 WHEN regexp_like(heap_used_after, '\d+\.?\d*G$') then cast(replace(heap_used_after, 'G') as double) * 1024 * 1024 * 1024 ELSE 0.0 END ) / ( CASE WHEN regexp_like(heap_capacity_after, '\d+\.?\d*B$') then cast(replace(heap_capacity_after, 'B') as double) WHEN regexp_like(heap_capacity_after, '\d+\.?\d*K$') then cast(replace(heap_capacity_after, 'K') as double) * 1024 WHEN regexp_like(heap_capacity_after, '\d+\.?\d*M$') then cast(replace(heap_capacity_after, 'M') as double) * 1024 * 1024 WHEN regexp_like(heap_capacity_after, '\d+\.?\d*G$') then cast(replace(heap_capacity_after, 'G') as double) * 1024 * 1024 * 1024 ELSE 1.0 END )
没有人希望保留上面一大坨代码,只为了计算一个占比。
更多案例
在平时的数据分析工作中,我们还有很多这样的案例,比如:
由于数据单位不一,无法按大小排序...
由于数据太大,想转换成方便阅读的大小...
时间单位不一,无法进行汇总计算...
现在,麻烦解决了
现在,SLS新增了单位转换函数,用来高效解决此类问题,专心为您排忧解难。
DataSize转换函数
针对上述示例,只需如下的简洁SQL即可:
不管heap_used_after的单位是B,是KB,是MB,还是GB,to_data_size_B()函数都可以统一转到以Byte为单位的大小。
您还可以使用以下函数,将数据对齐转换到对应的单位:
- to_data_size_B,将任意单位的数据转换为以Byte为单位的大小
- to_data_size_KB,将任意单位的数据转换为以KB为单位的大小
- to_data_size_MB,将任意单位的数据转换为以MB为单位的大小
- to_data_size_GB,将任意单位的数据转换为以GB为单位的大小
- to_data_size_TB,将任意单位的数据转换为以TB为单位的大小
-- 将data_size转换为Byte单位 select '50128371B' as data_size, to_data_size_B('50128371B'); data_size | _col1 -----------+------------- 50128371B | 5.0128371E7 -- 将data_size转换为KB单位 select '50128371B' as data_size, to_data_size_KB('50128371B'); data_size | _col1 -----------+---------- 50128371B | 48953.49 -- 将data_size转换为MB单位 select '50128371B' as data_size, to_data_size_MB('50128371B'); data_size | _col1 -----------+------- 50128371B | 47.81 -- 将data_size转换为GB单位 select '50128371B' as data_size, to_data_size_GB('50128371B'); data_size | _col1 -----------+------- 50128371B | 0.05
时间间隔转换函数
时间间隔(duration)同样也是非常常见的日志和指标数据,常用于表示系统执行一个请求的耗时,它的大小往往随请求大小、系统负载等因素而变化,具体ns、us、ms、s、m、h、d等不同的单位。
针对时间间隔数据,SLS提供了相应的转换函数如下:
- to_nanoseconds(),将任意单位的时间间隔转换为以纳秒为单位的大小
- to_microseconds(),将任意单位的时间间隔转换为以微秒为单位的大小
- to_milliseconds(),将任意单位的时间间隔转换为以毫秒为单位的大小
- to_seconds(),将任意单位的时间间隔转换为以秒为单位的大小
- to_minutes(),将任意单位的时间间隔转换为以分钟为单位的大小
- to_hours(),将任意单位的时间间隔转换为以小时为单位的大小
- to_days(),将任意单位的时间间隔转换为以天为单位的大小
- to_most_succinct_time_unit(),将任意单位的时间间隔转换为方便阅读的最靠近的极简单位的大小
-- 统一对齐到微秒 select time, to_microseconds(time); time | _col1 -------+------------- 175ns | 0 312us | 312 18ms | 18000 32s | 32000000 1.2m | 72000000 0.56h | 2016000000 0.2d | 17280000000 -- 统一对齐到毫秒 select time, to_milliseconds(time); time | _col1 -------+---------- 175ns | 0 312us | 0 18ms | 18 32s | 32000 1.2m | 72000 0.56h | 2016000 0.2d | 17280000 -- 统一对齐到秒 select time, to_seconds(time); time | _col1 -------+------- 175ns | 0 312us | 0 18ms | 0 32s | 32 1.2m | 72 0.56h | 2016 0.2d | 17280 -- 转换为方便阅读的极简单位 select time, to_most_succinct_time_unit(time); time | _col1 -------+---------- 175ns | 175.00ns 312us | 312.00us 18ms | 18.00ms 32s | 32.00s 1.2m | 1.20m 0.56h | 33.60m 0.2d | 4.80h
此外,我们还专门提供了对时间间隔的解析函数:
- parse_duration()
- format_duration()
-- 对string类型的时间间隔进行解析,返回DAY-SECOND的表示形式 select time, parse_duration(time); time | _col1 -------+---------------- 175ns | 0 00:00:00.000 312us | 0 00:00:00.000 18ms | 0 00:00:00.018 32s | 0 00:00:32.000 1.2m | 0 00:01:12.000 0.56h | 0 00:33:36.000 0.2d | 0 04:48:00.000 -- 对double类型的秒级时间间隔进行格式化,返回可读的时间间隔字符串 select time, format_duration(time); time | _col1 ---------+--------------------------------- 12.0 | 12 seconds 134.0 | 2 minutes, 14 seconds 235.0 | 3 minutes, 55 seconds 12.4 | 12 seconds 283.1 | 4 minutes, 43 seconds 22415.4 | 6 hours, 13 minutes, 35 seconds
小结
在数据处理和分析过程中,数据单位或时间单位不一致,往往给分析工作带来困扰,降低了工作效率,使分析SQL变得复杂而臃肿。
SLS充分考虑到“这一点小麻烦”,为用户贴心地提供了相关的单位转换函数,可以在不同单位之间轻松地进行转换、统一单位、格式化为可读文本。
从此,您的数据转换烦恼将被消除。
进一步参考
SLS单位换算函数官方详细参考文档:点击进入
欢迎钉钉扫群加入阿里云-日志服务(SLS)技术交流, 获得第一手资料与支持
更多SLS的系列直播与培训视频会同步到B站,SLS的相关文章会同步到微信公众号与知乎敬请关注