2012-04-25 13 views
20

我有一個問題,我需要非常快速地將大量數據(500億行)加載到數據庫中(理想情況下小於30分鐘但速度更快),最近我建議查看postgresql(我失敗了與MySQL和看在hbase/cassandra)。我的設置是我有一個生成大量數據的集羣(目前有8臺服務器),我想在本地集羣中的每臺機器上本地運行數據庫,然後在本地快速寫入數據(或整個數據生成過程中)數據合併在一起。數據不是以任何順序,所以我不關心哪個特定的服務器(只要它最終在那裏)。自動分片postgresql?

我的問題是,有沒有什麼好的教程或學習PostgreSQL自動分片的地方(我發現像sykpe做自動分片但沒有教程的結果,我想自己玩這個)?我正在嘗試做什麼?由於數據不是以任何順序,我打算使用自動遞增的ID號碼,如果數據合併(這不再是一個大問題)會導致衝突嗎?

更新:弗蘭克的想法如下消除了我所問的自動遞增衝突問題。現在的問題基本上是,我如何才能瞭解自動分片,並支持將數據分佈式上傳到多個服務器?

+1

我已經在<5分鐘內將大約1000萬行加載到postgres數據庫中,所以我可以自信地告訴你,在將數據加載到單個分片中時,這是一個非常重要的依賴資源:http:// www .postgresql.org/docs/8.1/static/populate.html這也看起來很有希望:http://pgbulkload.projects.postgresql.org/ – 2012-04-25 20:44:49

+9

'我打算使用自動遞增的ID號碼,這將導致衝突如果數據被合併?'只需增加10,並從不同的偏移量開始。服務器1使用標識1,11,21,31;服務器2使用ID 2,12,22,32 – 2012-04-25 20:46:04

+0

@FrankFarmer感謝您的鏈接和偉大的想法:增加。我認爲這需要一些複雜性,那麼我想這個問題只涉及到自動分片和分佈式上傳。 – Lostsoul 2012-04-25 20:47:42

回答

2

這裏有一些事情可能幫助:

  • 每個服務器上的數據庫應具有與該服務器的獨有特色小元數據表。比如它是哪個服務器;服務器可以按順序編號。除了該表的內容之外,嘗試儘可能保持每臺服務器上的架構儘可能相似可能是明智的做法。

  • 有了數十億行,你會希望bigint ID(或UUID等)。使用bigint,你可以爲每個服務器分配一個慷慨的範圍,並設置它的順序來使用它。例如。服務器1獲得1..1000000000000000,服務器2獲得1000000000000001至2000000000000000等。

  • 如果數據是簡單的數據點表中列(time timestamp, values double precision[])而不是更正確的(time timestamp, instrument_id int, value double precision)。這是一種幫助效率的明確的非正規化。 (我blogged我自己的這個方案的經驗)

1

抱歉,我沒有這方面的教程,但這裏有一個可能的解決方案的概要:

  • 負荷一八你數據轉換成在每個服務器
  • 對於最佳負載速度的PG實例,不使用插入件,但COPY方法
  • 當數據被加載時,不要在8個數據庫合併爲一個。相反,使用plProxy推出一個單獨的語句,一次查詢所有數據庫(或正確的,以滿足您的查詢)

如前所述,密鑰可能是一個問題。使用不重疊的序列或uuids或序列號與字符串前綴,不應太難解決。

您應該先在其中一臺服務器上進行COPY測試,看看您可以獲得多麼接近30分鐘的目標。如果你的數據不重要,並且你有最近的Postgresql版本,你可以嘗試使用unlogged tables,它應該快很多(但不是安全的)。聽起來像一個有趣的項目,祝你好運。

+0

謝謝,我會看看plProxy ..看起來真的很有趣。我會試試看,並沒有日誌表.. – Lostsoul 2012-04-26 03:31:15

14

第一:您是否真的需要將生成的數據直接插入關係數據庫?無論如何,你並不介意將它合併,所以爲什麼要插入數據庫呢?在你的位置,我會讓你的集羣節點寫入平面文件,可能是gzip的CSV數據。然後,我會使用類似pg_bulkload的工具批量導入併合並這些數據。

如果您確實需要直接插入關係數據庫:這是(的一部分)PgPool-II和(特別是)PgBouncer的用途。配置PgBouncer在不同節點之間進行負載平衡,你應該進行大致排序。

請注意,PostgreSQL是一個具有強大數據持久性保證的事務數據庫。這也意味着,如果你以一種簡單的方式使用它,做很多小寫操作可能會很慢。您必須考慮您願意在數據耐久性,速度和硬件成本之間做出什麼樣的權衡。

在極端情況下,每個INSERT都可以是它自己的事務,它在返回成功之前同步提交到磁盤。這將每秒事務數量限制爲您的磁盤子系統可以執行的fsync()數量,通常只有每秒數十或數百(無備用電池備份RAID控制器)。如果您沒有做任何特殊處理,並且您沒有將INSERT s包含在BEGINCOMMIT中,則這是默認設置。

在另一個極端,你說「我真的,如果我失去了所有數據不關心」,並使用unlogged tables爲您插入。這基本上賦予了數據庫權限,如果它不能保證它沒有問題 - 比如在操作系統崩潰,數據庫崩潰,電源丟失等情況下,你的數據就會丟失。

中間的地方是你可能想要的地方。這涉及到asynchronous commit,group commitscommit_delaycommit_siblings)的某種組合,將插入的批處理插入顯式爲BEGINEND等的組中。等等,而不是INSERT批處理,您可以一次執行COPY加載的幾千條記錄。所有這些都會影響數據的耐用性與速度。

對於快速批量插入,您還應該考慮插入除主鍵以外沒有任何索引的表。也許甚至沒有。一旦你的批量插入完成,創建索引。這將是一個更快的地獄。

+0

哇..感謝您的偉大答案。您的權利我根本不需要數據庫,但我試圖用它來與其他工作節點共享最終數據。因此,我的第一個過程會生成大量數據,但第二個過程使用羣集來根據以前的數據集分析數據(在同一天生成的方式相同)。我不知道如果我需要的中間地帶或更極端的未註冊的表,因爲如果數據庫死,如果我只用數據,那麼我就當它死了,可以再次重新啓動我的處理知道,但如果它沒有死,進展緩慢,那麼我會錯過我的最後期限。 – Lostsoul 2012-04-26 03:27:26

+0

您認爲在我的情況下將數據保存爲文件更有意義,然後只需上傳它?我想,既然我將不得不在數據庫中到底我還不如建立在我的程序,把它當我處理線程來分析,但如果它的速度更快只是在本地寫,然後批量上傳我可能只是做that..Also,我沒有在表中的任何索引(我的專欄是字符串的字典/ INT是我加載爲一個字符串,另一個是ID列,我認爲將是一個長整型.. )。所有其他決定考慮因素都是爲了提高速度 – Lostsoul 2012-04-26 03:30:04

+0

有關數據插入到數據庫碎片化的事情是,它是唯一有用的,如果你能在其分片的形式進行查詢。有一些工具可用(例如PL/Proxy),但它們比單個數據庫實例更復雜且難以使用。 OTOH,它們可以快很多。如果您不打算查詢碎片,而是想在分析數據之前合併數據,那麼最好將它寫成平面文件,然後將其插入最終的數據庫中。 – 2012-04-26 12:34:41

-1

您可以使用mySQL - 它支持跨羣集自動分片。

+2

我相信你在考慮MySQL Cluster,它是一種與MySQL本身分開的付費產品。 – Peeja 2014-07-15 15:06:54

1

使用citus進行PostgreSQL自動分片。另外this link是有幫助的。