ETL過程中資料精度不準確問題

RestCloud 發表於 2022-06-21

ETL過程中資料精度不準確問題

最近一位同學在使用Restcloud ETL產品做資料整合,出現資料傳輸到目標庫表後,資料精度不準確問題。

場景為:從oracle源表資料 格式為:number(21,6)將資料同步到mysql目標表資料格式為:float(21,6) ; 同步資料 發現 oracle是:538121.47 同步到mysql資料庫中:538121.50,看到這裡,不免有些同學會認為是產品的問題,我們一起來分析下。


首先,我們需要了解下資料在計算機中的區別。在計算機內部,小數有兩種表示方法: 定點數和浮點數

1、浮點型(float和double) 浮點型在資料庫中存放的是近似值
MySQL資料型別 含義
float(m,d) 單精度浮點型 8位精度(4位元組) m總個數,d⼩數位
double(m,d) 雙精度浮點型 16位精度(8位元組) m總個數,d⼩數位
設⼀個欄位定義為float(5,3),如果插⼊⼀個數123.45678,實際資料庫⾥
存的是123.457,但總個數還以實際為準,即6位。

2、定點數 定點型別在資料庫中存放的是精確值
浮點型在資料庫中存放的是近似值, ⽽定點型別在資料庫中存放的是精確。decimal(m,d) 引數m<65 是總個數,d<30且 d<m 是⼩數位。

對於單精度浮點數Float: 當資料範圍在±131072(65536×2)以內的時候,flo at資料精度是正確的,但是超出這個範圍的資料就不穩定,沒有發現有相關的引數設定建議:將float改成double或者decimal,兩者的差別是double是浮點計算,decimal是定點計算,會得到更精確的資料。
下面使用分析,


首先建立測試表

CREATE TABLE customer ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(45) DEFAULT NULL, age int(11) DEFAULT NULL, jinqian float(5,2) DEFAULT NULL, PRIMARY KEY (id) );

float(m,d)
m表示的是最大長度,d表示的顯示的小數位數。
例如上面的sql裡:float(5,2) 表示:這個浮點數最大長度為5,也就是五位,然後小數部分為2位,至於儲存範圍,取決於你是否定義了無符號。

無符號的話,最小 0.0 最大能儲存到99999.9,如果有符號的話,範圍是:-99999.9至99999.9。
預設大小為24位數字,精度大約7位數字(經測試為6位),當設定M大小大於24時,自動轉換為DOUBLE型別;同時設定M和D時不進行自動轉換。
小數位超過設定值,按四
舍五入儲存

INSERTINTO customer (id,name,age,jinqian)VALUES(111111111,'uu',15,90.012);
INSERTINTOcustomer(id,name,age,jinqian)VALUES(1111111111,'uu',15,90.018);


上面兩個分別被儲存為

總結
從上面的分析,我們可以得出以下結論:
1、浮點數存在誤差問題;
2、對貨幣等對精度敏感的資料,應該用定點數表示或儲存;
3、程式設計中,如果用到浮點數,要特別注意誤差問題,並儘量避免做浮點數比較;
4、要注意浮點數中一些特殊值的處理


ETL過程中資料精度不準確問題


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70005218/viewspace-2901932/,如需轉載,請註明出處,否則將追究法律責任。