2010-02-04 57 views
7

我們目前正在考慮將Postgres改爲CouchDB以用於使用情況監控應用程序。一些數字:CouchDB的推薦文檔結構

大約2000個連接,每5分鐘輪詢一次,每天大約600,000個新行。在Postgres裏,我們存儲這些數據,按天分區:

t_usage {的service_id,時間戳,DATA_IN,DATA_OUT}
t_usage_20100101繼承t_usage。
t_usage_20100102繼承t_usage。等等。

我們用樂觀的存儲過程編寫數據,假定存在分區並在必要時創建分區。我們可以很快插入。

對於數據,我們使用的情況下,在重要性和當前性能的順序讀是:
*單服務,單日使用方法:良好的性能
*多種服務,月使用方法:性能不佳
*單服務,月使用方法:性能不佳
*多服務,多月:非常差的性能
*多服務,單日:良好性能

這是有道理的,因爲分區幾天優化,這是迄今爲止我們最imp ortant用例。但是,我們正在研究改進二級要求的方法。

我們經常需要以小時爲參數來查詢查詢,例如,只在上午8點到下午6點之間給出結果,因此彙總表的用途有限。 (這些參數會以足夠的頻率更改,以至於無法創建多個數據彙總表)。

在這種背景下,第一個問題是:CouchDB是否適合這些數據?如果是這樣,在上述用例的情況下,如何最好地對CouchDB文檔中的數據建模?到目前爲止,我已經把一些選項,我們都在標杆的過程是(_id,_rev除外):

一個文檔每連接每一天

{ 
    service_id:555 
    day:20100101 
    usage: {1265248762: {in:584,out:11342}, 1265249062: {in:94,out:1242}} 
} 

大約60,000個月新文檔。大多數新數據將是對現有文檔的更新,而不是新文檔。

(這裏,使用中的對象被鎖定在輪詢的時間戳上,並且值被字節輸入和輸出)。

一個文檔每連接每月

{ 
    service_id:555 
    month:201001 
    usage: {1265248762: {in:584,out:11342}, 1265249062: {in:94,out:1242}} 
} 

約2,000個月新文檔。適度更新所需的現有文檔。

一個文檔中每個數據的收集行

{ 
    service_id:555 
    timestamp:1265248762 
    in:584 
    out:11342 
} 
{ 
    service_id:555 
    timestamp:1265249062 
    in:94 
    out:1242 
} 

大約有1500萬新文檔一個月。所有數據都將插入到新文檔中。插入速度更快,但是我對於一年或兩年後擁有數億份文檔的效率會有何疑問。文件IO看起來似乎過分(儘管我是第一個承認我沒有完全理解它的機制)。

我想在一個面向文檔的方式來處理這一點,雖然打破了RDMS習慣是很難:)你只能微創參數化的意見,以及有我有點擔心的事實。也就是說,以上哪一種最合適?有沒有其他格式我沒有考慮哪個會更好?

在此先感謝,

傑米。

回答

10

我不認爲這是一個可怕的想法。

讓我們考慮一下你的連接/月份情況。

假設一個條目〜40(這是大手筆)字符,你會得到每月〜8200項,您的最終文件大小是350K〜長在月底。

這意味着,去全通徑,你可以閱讀和寫作2000 350K的文件每5分鐘。

I/O明智的,這是小於6 MB/s,這讀寫,平均的時間5米的窗口。即使在今天的低端硬件中也是如此。

但是,還有另一個問題。當您存儲該文檔時,Couch將評估其內容以構建其視圖,因此Couch將分析350K文檔。我擔心的是(最後檢查一下,但已經有一段時間了),我不相信Couch在CPU內核上的伸縮性很好,所以這可以輕鬆鎖定Couch將要使用的單個CPU內核。我希望Couch能夠讀取,解析和處理2 MB/s,但我坦率地不知道。有了它的所有好處,erlang並不是直線計算機語言中最好的長途屁股。

最後的擔心是跟上數據庫。這將在本月底每5分鐘寫入700 MB。使用Couchs體系結構(僅限追加),您將每5分鐘寫入700MB數據,即每小時8.1GB,並在24小時後寫入201GB。

DB壓縮後,粉碎到700MB(單月),但在這個過程中,文件會越來越大,而且相當快。

在檢索方面,這些大文件不會嚇倒我。加載一個350K的JSON文檔,是的,它很大,但並不是那麼大,而不是現代硬件。公告板上的頭像比這個更大。所以,我想,任何你想要做的關於一個月的連接活動的事情都會非常快。在整個連接中,顯然你抓的越多,獲得的代價就越高(所有2000個連接都是700MB)。 700MB是一個真正具有實際影響力的數字。另外,你的過程需要積極地拋出你不關心的數據,這樣可以丟棄瑕疵(除非你想在報告過程中加載700MB的堆)。

鑑於這些數字,連接/日可能是一個更好的選擇,因爲你可以控制的粒度好一點。然而,坦率地說,我會選擇最粗糙的文檔,因爲我認爲這樣可以讓你從數據庫中獲得最大的價值,僅僅因爲今天所有的頭部搜索和滾動旋轉都是殺死大量I/O性能的原因,許多磁盤流數據非常好。較大的文檔(假設位置良好的數據,因爲沙發不斷壓縮,這不應該是一個問題)流更多比尋求。與磁盤相比,在內存中尋找是「免費的」。

通過一切手段在我們的硬件上運行您自己的測試,但要把所有這些考慮放在心上。

編輯:

更多的實驗之後...

情侶的有趣的觀察。

在導入大型文檔的過程中,CPU對於I/O速度同樣重要。這是因爲通過將JSON轉換爲供視圖使用的內部模型消耗了大量的編組和CPU。通過使用大型文件(350k),我的CPU非常出色(350%)。相比之下,對於較小的文件,它們以200%的速度嗡嗡作響,儘管總體而言,它們是相同的信息,只是大致不同。

對於I/O,在350K文檔中,我繪製的是11MB/sec,但是較小的文檔只有8MB/sec。

壓實似乎幾乎是I/O限制。我很難在I/O潛力上獲得好的數字。緩存文件的副本推送40 + MB /秒。壓實速度約爲8MB /秒。但這與原始負載一致(假設沙發正在通過消息移動東西消息)。 CPU比較低,因爲它處理較少(不解釋JSON有效負載或重建視圖),而且它是一個單獨的CPU。

最後,爲了閱讀,我試圖轉儲出整個數據庫。一個CPU與此掛鉤,我的I/O相當低。我確定CouchDB文件實際上沒有被緩存,我的機器有很多內存,所以很多東西都被緩存了。通過_all_docs的原始轉儲僅爲大約1 MB /秒。這幾乎是所有尋求和轉動的延遲。當我用大文檔做這件事時,I/O速度達到3 MB /秒,這只是表明了流式傳輸的影響,我提到了大文檔的優勢。

而且應該指出的是,Couch網站上有關於改善性能的技術,我沒有遵循。值得注意的是我使用隨機ID。最後,這並不是衡量Couch性能的標準,而是負載看起來最終的結果。我認爲大文件與小文件的區別很有趣。

最後,最終的性能並不像使用硬件對應用程序執行足夠好的性能那麼重要。正如你所提到的,你是在做自己的測試,而這纔是真正重要的。

+0

CouchDB將爲視圖服務器啓動多個系統進程來處理視圖,因此它可以在多個內核之間進行縮放。 CouchDB的其餘部分在Erlang中,並且在使用多個內核方面也很出色。 – mikeal 2010-02-06 05:58:41

+0

你說得對。我運行了一個測試,並且將這些大文檔中的2000個(每個插入100個同時進行的20個進程)插入v0.9 Couch實例。在4核心2.66G Mac Pro上,這些插件基本上是3分30秒。沙發佔了CPU的350%。最後磁盤文件是〜2G。即使壓實後,它幾乎沒有改變。相反,插入2000個「單日」文件需要18秒。當然,速度要快得多。 3分30秒太接近他們擁有的5米窗口。 18歲要好得多。雖然壓實需要近3百萬美元。 – 2010-02-06 09:17:56

+0

非常感謝,因爲這是一個很好的開始。我們已經運行了一些基準測試,發現和你一樣。我們將要面對的主要問題是對數據的不斷更新 - 看起來對於「整個月份」文檔來說它會變得非常慢。只要我們能夠經常壓縮,希望我們會好起來的。 這是一個恥辱,我們不能去每個數據點的文件,但正如你懷疑文件IO似乎是禁止的。不幸的是要更新任何其他類型的文件,我們需要閱讀之前,我們可以寫,以獲得_rev ... – majelbstoat 2010-02-07 13:29:24