天天看點

兩種檢查資料重複性的方法

我們在ETL測試過程中經常甚至是必須要檢測某一批資料中的某些次元在表範圍内是否重複。

本文就介紹兩種檢測資料重複的簡單方法。

方法1:

SQL法

如果這些資料在資料庫中,那完全簡單而且OK。具體方法為:

select (sum(c)-count(c)) uniq
from (
    select count(1) c
    from   table_t
    group by col1,col2,....coln
) a
           

 如果結果為0,則說明對應的次元上滿足唯一性要求。

方法2:

Linux指令法

有時候,我們得到一個體積較大的資料檔案(從資料倉庫導出做别用),想要檢查這個檔案中的某些個字段次元上是否滿足唯一性要求。當然,我們可以将這個檔案導回到資料庫,然後再寫上面的SQL語句搞定。但是這樣做難免小題大作了。因為,我們的需求很簡單,而且由于資料檔案較大,搞到資料庫裡對存儲、計算、資源維護都是一種浪費。

現在分量中情況處理:

(1)資料待檢查次元上有序:

我們可以通過如下指令來解決這個問題:

cut -d "[分隔符]" -f [你需要的次元] [你的資料檔案] | uniq -c | grep -v -e '^ \+1 ' | wc -l      

上面的方法,采用最粗暴的周遊檔案方法搞定,同樣也是最簡單的,比其導入資料庫,配置設定額外存儲空間,建立索引,SQL查詢計算等來講簡直是太簡單了。

而且單從SQL與linux command執行效率來講,SQL中的group by效率不見得比Linux command高。

如果我們需要統計所有次元上有無重複資料,則更簡便,方法為:

uniq -c [你的資料檔案] | grep -v -e '^ \+1 ' | wc -l      

一個實際示例:

一個千萬級的資料檔案進行次元唯一性檢查時,在我的桌上型電腦上安裝的虛拟機上(哈哈,性能夠差的)執行大概需要10秒左右的樣子。

(2)資料待檢查次元上無序:

面對這樣的資料,uniq要想發揮作用,則必須在uniq之前進行sort,而對于大資料來講sort是不可行的。

因為無論如何sort也需要nlogn的時間複雜度才能OK,而接着uniq也需要n的複雜度。而且,sort需要将全部資料讀入記憶體。

由于資料無序,此時最優的方法就是掃描一遍資料得出結果。這需要借助我們上一篇博文中介紹的awk的方法完成,不過我們不需要計算sum值。

代碼稍作修改,count.awk 檔案如下:

BEGIN{
}
{
    if($0 in count){
        count[$0]+=1;
    }
    else{
        count[$0] =1;
    }
}
END{
    for(x in count){
        print count[x]:"x";
    }
}      

此時,借助count.awk的功能,實作方案為:

grep -v -e '^$' [你的檔案] | cut -d "[分隔符]" -f [次元] | awk -f count.awk | grep -v -e '^1:' | wc -l      

首先去除空行,然後選取需要檢查的次元,傳入count.awk檔案中統計次元上資料出現的次數,最後計算出現不止一次的資料又多少個。

如果結果為0,則說明檢查次元上資料唯一,否則不唯一。

例如,一個檔案為:

a,b,c

a,c,e

a,b,e

a,c,f

a,d,g

a,e,g

運作上述指令檢查前兩個次元上是否有重複,結果為:

2   --a,b和a,c分别都出現了兩次。

如果檢查全部次元上的唯一性,則上述指令中的 [cut] 部分就可以不用了。