Postgresql

通過刪除+插入更新表是否比與臨時表合併更好?

  • January 19, 2022

我在 Postgres 中有兩張桌子。第一個表有 120 列(股票指標,如退貨、銷售額等),第二個表有 5 列,具有一對多關係,並且與第一個表有級聯刪除約束(此表包含 10 年的股票預測所有上市公司的數據)。隨著股票價格每天的變動,所有這些表值都應該每天更新。

在我的項目中,有兩種​​方法可以更新數據庫:

  1. 一個是在 API 級別上,其中僅更新第一個表中的一行。這取決於使用者想要更新的次數,但使用者端不會有很多更新。
  2. 另一個每週執行一次,其中兩個表中的所有行都會更新。

對於這兩種方式,我首先刪除第一個表中的記錄,然後使用 python(for-loop)在兩個表中插入數據。

刪除和插入比創建臨時表並將其與舊表合併(更新現有記錄並插入不存在的行)更好的方法嗎?

第一張表有120列,每個主鍵有一行

根據定義,“主鍵”唯一標識每一行。

我懷疑這不是你的意思。

第二個表有5列,每個主鍵有1000行

那麼它不能是第二個表的“主鍵”。

假設你的意思是第二個表每個對應的有 1000 行

$$ Primary $$鍵入第一個表。

… 兩種更新數據庫的方法 …

一種是在 API 級別上,僅更新一個主鍵。

另一個……所有主鍵都更新了。

任何記錄的主鍵都應在首次創建記錄時生成/儲存,並且應在該記錄的整個生命週期內保持**不變,直到該記錄最終被銷毀

什麼都不應該更新主鍵值。

這是一個非常昂貴的操作,會在它發生時鎖定數據庫,並且從所有意圖和目的來看,這完全是浪費時間。如果您為每條記錄使用代理數字 id 以“更容易”將數據庫中的事物聯繫在一起,那麼該值永遠不會改變(並且數據庫之外的任何人都不應該看到它) .

對數據庫的每一次更改都會被記錄下來,因此通過“重寫”每條記錄來有效地刪除和重新創建表將錘擊您的磁碟系統,其中包含每條已刪除記錄和每條插入記錄的映像。這將是很多磁碟活動和 CPU 負載以及記錄/表鎖定和應用程序性能影響 - 對於您可能根本不應該做的事情。

一個類比:

考慮一下如果您的銀行決定在其他人關閉他們的賬戶時重新編號每個人的賬戶的效果……這就是我們在這裡談論的事情。

您可能對 Phil w 的回復中確定的術語“主鍵”存在術語或其他理解問題。跳過對行進行的操作:

通過 delete+insert 更新表比*<anything>更好*

不。

除了對同一行執行多個操作引起的性能問題,以及如果您使用基於日誌的備份、複製等的其他資源問題,delete-then-insert 可能會導致意外的數據失去或損壞.

如果使用子數據定義了任何外鍵,也ON CASCADE DELETE將被靜默刪除,並且在您重新插入行時不會恢復。即使兩者都在單個顯式事務中完成也是如此:在採取級聯刪除操作之前,數據庫不會等待查看 PK 值是否重新出現。如果級聯刪除由於以這種方式定義的更多 FK 導致進一步級聯,則這可能導致更多表中的進一步刪除。

同樣,觸發器可能會導致數據失去,也可能會導致其他邏輯損壞(因為它們可以做的不僅僅是刪除)或意外操作(由於它們對其他數據所做的更改會被應用程序的其他部分做出反應)。

當然 delete+insert 如果沒有定義這樣的動作是安全的,但你不知道它們以後永遠不會被添加。或者您以後可能為某些東西添加它們,但由於您沒有時間更改的現有程式碼依賴於它們不存在而無法添加它們。對於這個特定的 DB+程式碼,它可能永遠都很好,但我會養成盡快避免使用這些方法的習慣,這樣你就不必忘記以後使用它們的習慣。

在可能/實際的情況下,讓您的程式碼按字面意思執行它在功能上所做的事情:對行的更新應該是更新¹,而不是刪除後插入。這具有使您的程式碼對其他任何人都更清晰的額外優勢²。

$$ 1 $$好吧,為了更完整,合併和更新操作也是這些行的更新,如果您的數據庫支持這樣的結構,因為它們實際上是圍繞插入/更新/刪除原始操作的語法糖。

$$ 2 $$“任何人”可能是未來的你,幾乎不記得寫過 ocde e 已被要求進行修改

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