Postgresql

大文本正文的雜湊支持唯一約束的衝突解決

  • May 6, 2021

所以我們剛剛遇到

ERROR: index row size 2736 exceeds maximum 2712 for index "foo__bar__un"
 Hint: Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.

foo是表,bar是列和un“唯一”)

考慮值的 MD5 雜湊的函式索引

好吧,讓我們。這很簡單:

ALTER TABLE foo DROP CONSTRAINT foo__bar__un;
CREATE UNIQUE INDEX foo__bar__un ON foo(md5(bar));

到目前為止,很好,這是錯誤提示中提出並在網上很多地方找到的解決方案。

不過,我還沒有發現如何處理碰撞。

就我而言,我有一個包含生化實驗結果的數據庫。我不能只是去找科學家說“你能稍微改變一下你的結果,以便我們可以將它實際儲存在我們的數據庫中嗎?是的,我知道這可能會花費你的幾個客戶的生命,而你個人可能金額高得令人望而卻步,但我不能讓你以其他方式存放它”。

(實際上,我們只是在那之前放棄約束,但你明白我的意思。)

我確實知道碰撞幾乎可以忽略不計,但我寧願知道如果萬一發生碰撞,我可以處理它們。鑑於這不僅僅是我們遇到的利基問題,我敢肯定我不是唯一一個對此感到疑惑的人。

那麼在這種情況下,處理碰撞的方法*是什麼?*如果可能的話,我寧願不必用基於觸發器的 DIY 解決方法替換唯一索引。

例如,我能否以某種方式強行對具有相同雜湊的條目執行額外的“等於”檢查,並且僅在它們實際存在時才拋出異常?

我不知道為什么生化實驗的結果首先會被強制要求是唯一的,但是您可以使用排除約束來測試是否相等。它將通過逐個字元的比較來自動解決雜湊衝突。

alter table foo add constraint foo__bar__un exclude using hash (bar with =);

但是你應該升級到比 9.6 更新的東西。

如果您對一年中有 2 128天的生日問題(即不同 MD5 雜湊的數量)進行平方近似,並且您想知道有多少表行上的衝突機率超過 0.000000001,那麼您最終會得到

SELECT sqrt(2 * 2 ^ 128 * 1E-9);
     sqrt       
═════════════════
824963474247119
(1 row)

因此,即使您有近千萬億行,發生碰撞的風險也非常小,以至於我更擔心飛機會與數據中心發生碰撞。

引用自:https://dba.stackexchange.com/questions/291057