![](/img/trans.png)
[英]Determining if a program is fast, memory-efficient and does not have large time-complexity
[英]Memory-efficient distributed approach to determining unique values?
我正在嘗試在非常大的原始非規范化CSV表中規范化列。 列值是短字符串(10-100字節)。 我正試圖找到一種比我目前的方法更快的解決方案。
input.csv
john,london
jean,paris
bill,london
轉換為以下文件:
input.normalized.csv
1,1
2,2
3,1
input.col1.csv
1,john
2,jean
3,bill
input.col2.csv
1,london
2,paris
我目前有兩種方法來規范化這些數據集。
單通道方法,在關聯數組中存儲列values -> normalized_id
值(在我的例子中是Java HashMap)。 這會在某些時候耗盡內存,但是當它可以將所有內容存儲在內存中時它會很快。 降低內存使用量的一種簡單方法是每列執行一次傳遞。
基於排序的多通道方法。 列值附加其行號,然后進行排序(以內存高效的合並排序方式)。 例如,列值london,paris,london
附有行號,然后進行排序: london;1,london;3,paris;2
。
我現在可以擁有一個“唯一值計數器”,只需將每個值與之前的值進行比較(例如倫敦==倫敦,所以不要增加唯一值計數器)。 最后,我有一對unique_id,linenum
對,我可以按行號排序以重建規范化列。 然后可以在一次通過中合並列。
這種方法可以在非常有限的內存中完成,具體取決於所應用的排序算法的內存使用情況。 好消息是,這種方法很容易在像hadoop這樣的方法中實現,利用它的分布式排序步驟。
與單通道方法(或單通道每列方法)相比,多通道方法非常緩慢。 所以我想知道優化這種方法的最佳方法是什么,或者是否有人可以建議其他方法?
我估計我正在尋找某種類型的(分布式)鍵值存儲,它具有盡可能低的內存使用率。
在我看來,使用Trove將是使用Java HashMaps的一個好的,簡單的替代方案,但我想要一些可以為我處理密鑰分發的東西。
Redis可能是一個不錯的選擇,但我並沒有對每個鍵值對的內存使用情況印象深刻。
你知道輸入列的粗略數量級嗎? 如果是這樣,您不需要保留原始輸入文件順序? 然后,您可以使用足夠大的哈希函數來避免輸入鍵的沖突。
如果你堅持擁有密集的連續密鑰空間,那么你已經涵蓋了兩個主要選擇。 你當然可以嘗試redis,我已經看到它用於數百萬的鍵值對,但它可能不會擴展到那個以上。 你也可以試試memcached。 它的內存開銷可能略低於redis,但我肯定會嘗試兩者,因為它們對於這種特殊用法非常相似。 您實際上並不需要Redis的高級數據結構。
如果你需要更多的鍵值而不是你可以在一台機器上存儲在內存中,那么你可能會回歸到像BDB或Kyoto cabinet這樣的東西,但最終這一步將成為你處理的瓶頸。 另一個紅旗是,如果你可以在一台機器的內存中安裝整列,那你為什么要使用Hadoop?
老實說,依賴密集有序的主鍵是NoSQL DB中首先拋出的東西之一,因為它假定一個單獨的協調主。 如果你可以允許甚至一些間隙,那么你可以做類似於矢量時鍾的事情。
最后一種選擇是使用map-reduce作業按鍵收集所有重復值,然后使用某個外部事務DB計數器分配唯一值。 但是,map-reduce工作本質上是一種多遍方法,因此可能更糟。 主要優點是你將獲得一些IO並行性。 (雖然id賦值仍然是一個串行事務。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.