PostgreSQL 中如何delete重複資料

2021-10-25 06:59:50 字數 2344 閱讀 2220

時常有這樣的case: db例項執行一段時間後,發現需要給1個table中的某(些)欄位加unique 約束,

但建立unique constraints(或 index)時, 報出 detail: key (col)=(value) is duplicated !

此時就需要先按照一定邏輯將重複資料僅保留1條, 將冗餘的delete掉

delete資料, 重點自然在於定位所有待delete的row, 或需要保留的row.

以假設業務要求要保留如下test表中每組info重複值中id最小的row為例

使用高階資料型別array及其強大的function, 一次定位需要delete的row

思路同 方法1, 讓我們體驗一下 window function

排除法, 逆向定位

思路同 方法3

先定位存在重複值的組大集合,再排除小集合

思路同 方法5

將所有存在重複值的組找到, 然後逐一定位需要保留每組中的最小id, 其餘delete

如果應用可以接受短暫停止寫入, 可以將所需唯一資料複製到新錶

放在事務裡是為了保證所做操作原子性, 避免出現瞬間無表可用的視窗期

注: 為了便於與其他方式對比, 方法8會按照保留id的方式測試, 如果不保留id, group by 比 distinct 執行速度略快.

由於query在 table 資料分布不同的情況下執行效率存在差異, 所以我們構造3組測試資料進行對比

資料分布

分析上表可知,

使用正向思維(方法1,2), 平均執行時間會隨著冗餘資料的增加而增加, 在冗餘資料較少時, 推薦方法2;

使用逆向思維(方法3,4), 平均執行時間會隨著冗餘資料的增加而減少, 在冗餘資料較多時, 推薦方法4;

正逆結合的思維(方法5,6)平均執行時間並不佔優勢, 原因是需要2次subquery來最終定位資料;

方法7 方法7 執行總時間最長(隨著單條sql的總條數的增加而增加),

但實際上對db例項的衝擊最小, 把1個長時間的對大量row 的lock, 離散化為僅對單個row或幾個row的極短時間的lock,

在壓力較大的生產環境中, 推薦此方法;

方法8 步驟稍繁, 在實際生產環境中由於table的字段可能較多,且整個table的(包括所有index)都會重建, 所以速度並不佔優, 但卻順便把table徹底維護了一下 , 對於udpate, delete非常頻繁的table, total size(包括所有index)會大為縮小(由於mvcc), 綜合性能會明顯提公升.

看一下delete 的語法

所以其實還有其他一些具體方法, 比如 使用 with queries構造臨時表, 使用 using using_list 替代子查詢, 使用儲存過程將方法1封裝起來(不推薦,因為這樣整個delete過程為乙個大事務)等等;

但整體思路無外乎上面的套路, 條條大路通羅馬,結合table中資料分布情況(具體問題具體分析),選擇效率較高, 且是您最鍾情的那個style就可以了.

壓力大的線上生產db例項(尤其是交易系統), 首選對生產衝擊最小的,

壓力不大的生產db例項或db beta/dev 例項首選一條sql且執行時間快的方法。

重複值delete之後,就可以建立唯一索引了,方法如下:

postgresql 中如何delete重複資料 :

PostgreSQL中如何關閉死鎖的程序

由於使用的postgresql資料庫,沒有資料。只好進行谷歌。最終在乙個英文論壇中發現了解決方法。如下 1.檢索出死鎖程序的id。select from pg stat activity where datname 死鎖的資料庫id 檢索出來的字段中,wating 2.將程序殺掉。select pg...

AngularJS中Scope間通訊Demo

在angularjs中,每乙個controller都有對應的scope,而scope間有時候需要通訊。比如有如下的乙個controller巢狀 body ng controller table ng controller productctrl tr ng repeat product in pro...

PostgreSQL如何匯入SJIS字符集的檔案

磨礪技術珠磯,踐行資料之道,追求卓越價值 回到上一級頁面 postgresql雜記頁 回到頂級頁面 postgresql索引頁 作者 高健 luckyjackgao gmail.com 外部檔案來自於windows,日語sjis字符集。由於sjis字符集和標準的posix有衝突,故linux平台一般...