2009-06-29 28 views
9

我在計劃數據庫以存儲大量文本。 (博客文章,新聞文章等)數據庫需要標題,內容(最多5萬個字符),日期,鏈接和語言字段。同一內容不能在一個鏈接上發生。舊內容(例如30天以上)將被刪除。PostgreSQL:在大型數據庫上定義主鍵

現在,問題是主鍵。我可以設置一個自動遞增(SERIAL類型)字段並將其用作主鍵。但是,這看起來很愚蠢,並且浪費了光盤空間,因爲該領域不會有任何目的,只能成爲主要關鍵。 (並且該字段最終可能會用完,或者不是?)並且總是存在其他性能問題:插入的每個新行的內容都需要檢查重複項。因此,我提出的主鍵的另一個解決方案是計算內容+鏈接值的sha256散列,然後將其放在新的「散列」列中,並將其用作主鍵。一石二鳥。當然,這個問題是散列衝突。這是一個很大的威脅嗎?

我對PostgreSQL沒有任何經驗,對DBMS的一般經驗也很少,所以我希望在創建一個具有高速公路上蝸牛性能特徵的數據庫(可怕的比較)之前有第二種意見。

如果您對大型數據庫有任何經驗,請幫助我。在我的情況下,將64字符的字符串設置爲主鍵字段是個好主意嗎? (因爲我的印象是,一般這是避免)

回答

9

只是做這個確切的測試相當大中型DB(200GB +),BIGSERIAL由相當大比分獲勝。生成速度更快,加入速度更快,代碼更少,佔地面積更小。由於postgres存儲它的方式,bigint與正常int相比可以忽略不計。在您不必擔心溢出bigint之前,您的內容中就會耗盡存儲空間。完成計算後的散列vs bigint - 一路代替bigint。

2

幾點建議:

  • 64位的主鍵整數的磁盤存儲是微不足道的,不管你有多少內容有。
  • 你永遠不會碰撞SHA256,並將其作爲唯一的ID使用並不是一個壞主意。

哈希方法的一個好處是您沒有單個序列源來生成新的主鍵。如果您的數據庫需要以某種方式進行分段(如地理分佈)以供將來擴展,那麼這很有用,因爲您不必擔心衝突或產生序列的單點故障。

從編碼的角度來看,擁有單個主鍵對於加入未來可能添加的額外數據表至關重要。我強烈建議你使用一個。對你提出的方法都有好處,但散列方法可能是首選方法,僅僅是因爲自動增量/序列值有時會導致可伸縮性問題。

+1

如果您使用SHA256作爲主鍵,它不一定是不可變的嗎?如果內容+鏈接值更改會發生什麼? – 2009-06-29 19:37:45

+0

哈維,好點,但如果一個會改變一行的內容值,那麼我會檢查是否存在新內容+鏈接alredy的散列。如果是這樣,則不會發生變化。 – KRTac 2009-06-29 19:50:25

+0

因此,如果內容發生變化,您創建一個新的記錄? – 2009-06-29 20:31:37

1

散列是主鍵的壞主意。它們使得插入在表中隨機排列,因爲事物必須重新分配(儘管Postgres實際上並不像其他人那樣應用),這會非常昂貴。我建議一個連續的主鍵,它可能是一個細粒度的時間戳/時間戳,後面跟着連續數字,讓你用石頭殺死兩隻鳥,還有第二個包含你的散列碼的唯一索引。請記住,您希望將主鍵保持爲較小(64位或更少)的列。

請參閱http://en.wikipedia.org/wiki/Birthday_attack#The_mathematics的表格,以便您確信自己不會碰撞。

不要忘了抽真空。

3

在主鍵整數用完之前,你必須有很多記錄。

連接的整數將比64個字符的字符串主鍵要快。編寫查詢的人也更容易處理。

如果碰撞有可能發生,您不能使用散列作爲主鍵。主鍵必須通過定義以獨特的方式進行定義。

我見過數百個生產數據庫爲不同的公司和政府實體,而不是一個使用哈希主鍵。認爲可能有一個原因?

但是,它似乎很愚蠢和浪費光盤空間,因爲該字段不會有任何目的,而是成爲主鍵。

由於代理主鍵應該總是沒有意義,除非作爲主鍵,我不確定你的反對意見是什麼。

3

我會選擇使用代理鍵,即。一個不屬於您的應用程序業務數據的關鍵。當您處理每個記錄最多50千字節的文本時,額外的64位整數空間要求可以忽略不計。只要您開始將此密鑰用作其他表中的外鍵,您實際上就會使用或更少的空間。

如果散列基於的數據發生更改,則使用存儲在記錄中的數據的散列是主鍵的非常糟糕的候選者。然後你將改變主鍵,如果你有其他表與這個關係的關係,那麼你會更新所有地方的更新。

PS。一個類似的問題已經被問到並在這裏回答before

下面是關於該主題的另一個很好的寫了起來: http://www.agiledata.org/essays/keys.html

1

我會使用普通的32位整數作爲主鍵。我不認爲你會很快超過這個數字:-)整個維基百科有大約3,5百萬篇文章......如果你每天寫1000篇文章,那將需要將近6000年才能達到整數類型的最大值。