Postgresql

具有一個整數列、排序索引、具有重複主鍵的 Postgresql 表

  • June 24, 2013

我想在 PostgreSQL 中有一個具有以下屬性的表:

  • 一列有一個整數
  • 允許在此列中重複。重複將是罕見的。重複項在邏輯上沒有意義,將被整數上的 WHERE 子句刪除。桌子像一組一樣使用。
  • 列/行上的高效 ORDER BY+LIMIT,並使用該整數的 WHERE 子句進行刪除
  • INSERT 不應在該表或任何類型的唯一索引中執行任何查詢。INSERT 應該只為該表的主文件/主 btree 找到最佳頁面,並將該行插入其他兩行之間,按 ID 排序。(這就是為什麼必須允許重複,對主鍵的檢查會導致更多的磁碟搜尋,並可能導致事務失敗並導致死鎖)
  • INSERT 將批量發生(每個事務大約 1000 次)並且不能失敗,預計磁碟已滿等。不能有任何死鎖的機會。
  • 此表不應有額外的 btree 文件,因此沒有二級索引
  • 行應該佔用不多的空間,例如沒有 OID,所以很多行適合一頁。

我想不出解決所有這些問題的解決方案。

最簡單的事情是該列上的主索引。但這不允許重複。

我也可以使用二級索引,但這會導致每個 INSERT 的更多操作和更多的磁碟訪問。我真的很受磁碟搜尋的約束。

目前我最好的解決方案是在最後一個要點上妥協:我可以只用一個 PRIMARY KEY 覆蓋整數列和一個虛擬列,如 OID、時間戳列或 SERIAL 列。然後每一行(=主鍵)都是唯一的。但這會增加磁碟空間並減少每頁的行數。

有沒有機會擁有一種主鍵和重複項?我可以控制光碟上的主要 btree 文件的組織方式嗎?

(我在 StackOverflow 上發布了類似這個問題的相關問題,但我對我的目標非常不清楚。我希望這不會被視為垃圾郵件,這裡的這個問題是完全不同的)

我認為您是在問如何為您未描述的更普遍的問題實施您已經決定的解決方案。如果你要概述這應該解決的實際問題,你可能會得到關於如何解決它的更好的建議。

在提供的非常有限的資訊範圍內工作:


更新:我發現了你的另一個問題,你真的應該連結到它。您似乎正在嘗試滾動自己的消息隊列。不要那樣做。閱讀這些:

我有沒有說服你,你不應該嘗試自己做這件事?調查:


目前的 PostgreSQL 版本中沒有您想要的一些內容。例如:

  • INSERTs 不應在該表或任何類型的唯一索引中執行任何查詢。INSERT 應該只為該表的主文件/主 btree 找到最佳頁面,並將該行插入其他兩行之間,按 ID 排序。

這需要一個索引組織的表,而 PostgreSQL 還沒有。您將得到的最接近的將是一個帶有PRIMARY KEY. 在 PostgreSQL 9.2 上使用正常VACUUM時,您大部分時間都可以使用僅索引掃描來訪問它。

至於允許重複,您似乎根本不想允許它們,您只是說您想通過暫時允許它們來解決並發問題。

您可以在此期間刪除此類重複項,INSERT以便表本身不需要允許它們。但是,這會導致以下問題:

  • INSERT 將批量發生(每個事務大約 1000 次)並且不能失敗,預計磁碟已滿等。不能有任何死鎖的機會。

…假設這些插入同時發生在多個事務中。您將在檢查是否存在和插入之間存在競爭,這可能導致插入批次失敗並且必須重新嘗試。

我懷疑你最好的選擇是有一個沒有PRIMARY KEY. 只需在其上創建一個普通的 b-tree 索引,並讓表不帶PRIMARY KEY. 由於它確實沒有主鍵(唯一的列可能有重複),這是完全合理的。

(順便說一句,鑑於 SQL 應該是關於集合的,它讓我吃驚的是,“如果不存在的話,將這個條目添加到集合中”是多麼糟糕)。

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