Postgresql
大文本正文的雜湊支持唯一約束的衝突解決
所以我們剛剛遇到
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)
因此,即使您有近千萬億行,發生碰撞的風險也非常小,以至於我更擔心飛機會與數據中心發生碰撞。