將mysql數據同步到elasticsearch時,mysql的float類型出現精度損失及解決方法

場景描述

之前將mysql數據同步到ES,採用的是如下的架構,打造的是千萬級別的實時搜索系統

詳情請看 https://blog.csdn.net/laoyang360/article/details/52227541#commentBox

最近運營突然找到我說有一個問題就是爲什麼數據庫源表這種是

2.99腫麼變成了這個2.990000009536743,出現了精度上面的一些問題。一開始我也是一臉懵逼,以爲是ES的問題,但是一想好像不對,ES的數據類型就是浮點型,不可能是ES把2.99轉換成2.990000009536743了。

於是就開始分析了。

出問題只可能是三個位置:ES、mysql、同步過程

上面首先就排除了ES的問題,然後是同步的過程,經過驗證同步過程中是沒有這種騷操作的。那就只可能是mysql的問題

但是特別奇怪的是通過SQL語句查詢出來的數據是正常的呀。

於是查看了一下出現問題的字段類型,發現這個字段的類型居然是float(8, 2),搞得我一臉懵逼,

因爲

FLOAT類型用於表示近似數值數據類型。SQL標準 允許在關鍵字FLOAT後面的括號內選擇用位指定精度(但不能爲指數範圍)。MySQL還支持可選的只用於確定存儲大小的精度規定。0到23的精度對應 FLOAT列的4字節單精度。24到53的精度對應DOUBLE列的8字節雙精度。單精度浮點數用4字節(32bit)表示浮點數
採用IEEE754標準的計算機浮點數,在內部是用二進制表示的
如:7.22用32位二進制是表示不下的。
所以就不精確了。

好吧,看來是設計表的人的問題。哎!!!有點鬱悶

表數據量已經很大了,而且數據是很敏感的數據,線上好多服務都在用,改表結果是不存在了,所以還得我想辦法呀!!!

自己的解決思路很簡單,查詢出來的數據沒有問題,但是映射到ES上面的時候出現了精度問題,肯定是mysql類型的問題導致的,所以再同步過程中,進行下類型轉換即可,由於我是多表關聯製作寬表進行同步的,有updatetime字段,所以是使用的sql進行同步的。我把查詢出來的數據先轉換成char類型然後在轉換成decimal(8, 2)解決的,因爲我一開始嘗試轉換成char同步上去是2.99字符串,所以我就在此基礎上做了。可能有更好的辦法,反正解決了!!!,由於表的數據量很大了,所以使用這種方式可以進行更新修改同步,原來的數據是有的,線上查詢依舊可以正常使用,因爲索引mapping結構沒有變,至少算是一種還過得去的方法。如果表的數據量沒有過億,使用logstash-input-jdbc是可以的,過億了,還是老老實實自己寫個簡單的腳本去實現吧。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章