前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >clickhouse一个特殊的Inf类型数据引发的数据问题

clickhouse一个特殊的Inf类型数据引发的数据问题

作者头像
公众号-利志分享
发布2022-04-25 09:27:18
6290
发布2022-04-25 09:27:18
举报
文章被收录于专栏:利志分享

任何数除以0结果都是无穷大,不同的数据库客户端库对这个结果无穷大的处理都不一样,有一些问题值得我们去注意。

比如这样的一个sql:

代码语言:javascript
复制
select os_id,browser_id,browser_id/os_id gg from example

之前的脚本在mysql上执行通过go客户端读取结果是不会存在问题的,但是放到clickhouse上面执行,读取结果只会就发现会存在问题。具体问题请看下面我详细讲述。

问题:

自从通过用clickhouse做分析数据的仓库后,我们需要通过sql读取clickhouse的结果存储到mysql存储里面,让用户能读取,当时脚本一切都好好地,突然发现某一天的数据丢失了,重跑也没有数据,经过查证发现原始数据是有的,不可能这一天都没有数据。

问题追踪:

当时查了日志也没有发现日志错误,也没有发现有奔溃什么的,那天的统计原始数据也不多,后面就把统计之后的结果数据打印出来,放到线上去跑,后面发现返回的结果和之前的几天能读出来的数据多了个+Inf,同时发现之前的写入到mysql的脚本程序把错误也给忽略了(这里是代码质量问题,目前先不谈),查到这里,我就开始写个demo出来验证一下。

客户端代码如下:

代码语言:javascript
复制
package main

import (
        "encoding/json"
        "fmt"
        _ "github.com/ClickHouse/clickhouse-go"
        "github.com/jmoiron/sqlx"
)

func main() {
        connect, err := sqlx.Open("clickhouse", "tcp://127.0.0.1:9000?database=default&debug=true")
        if err != nil {
                fmt.Println(err)
                return
        }
        sql := "select os_id,browser_id,browser_id/os_id gg from example"
        rows, err := connect.Queryx(sql)
        if err != nil {
                fmt.Printf("connect DB Queryx, err:%v\n", err)
                return
        }
        var list []interface{}
        for rows.Next() {
                result := map[string]interface{}{}
                err := rows.MapScan(result)
                if err != nil {
                        fmt.Printf("scan err:%v", err)
                        return
                }
                fmt.Println(result)
                t, err := json.Marshal(result)
                fmt.Printf("xxx:%s%v\n", string(t), err)
                list = append(list, result)
        }
        t, err := json.Marshal(list)
        fmt.Printf("list:%s%v\n", string(t), err)
}
代码语言:javascript
复制
执行结果如下:
代码语言:javascript
复制
map[browser_id:54 gg:2.347826086956522 os_id:23]
xxx:{"browser_id":54,"gg":2.347826086956522,"os_id":23}<nil>
map[browser_id:54 gg:2.347826086956522 os_id:23]
xxx:{"browser_id":54,"gg":2.347826086956522,"os_id":23}<nil>
map[browser_id:54 gg:+Inf os_id:0]
xxx:json: unsupported value: +Inf

其实只有这里的json.Marshal才会报错:

代码语言:javascript
复制
json: unsupported value: +Inf

问题追踪完之后,通过测试确定问题是Inf造成了报错,然后数据结果没有写入到mysql中。

问题深入:

上面我们其实已经找到了问题,然而我并不满足此,通过深入发现同样的sql,mysql却不会存在报错,go的mysql客户端把无穷大转成了sql.RawBytes,go的clickhouse却直接把无穷大转化成一种数据类型+Inf,这种数据类型只有go的clickhouse客户端才有,json的库并不能处理这个类型。

问题解决:

1:把代码中该加error的地方加上

2:如果读clickhouse的数据的sql存在相处的类型,我们都必须手动处理结果为无穷大的情况:如果除数等于0则把结果赋值成0,这样计算的结果就能正常写到mysql中。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 利志分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档