2011-08-31 29 views
2

首先,我使用的是Postgres 9.1。像引用計數或數據庫行的共享指針?

我有一個名爲filepaths的表和其他表具有指向其相應文件路徑的id的行。有沒有一種通用的設計方法來引用計數文件路徑,以便在其他行被刪除並且不再有任何對特定文件路徑行的引用時,它也可以被刪除?

例子:

[filepaths] 
    1 | c:\windows\system32\test.exe 
    2 | c:\windows\calc.exe 

    [events_2011_08_30] 
    [1][timestamp][other data] [ filepaths = 1] 
    [2][timestamp][other data] [ filepaths = 2] 

    [events_2011_08_31] 
    [1][timestamp][other data] [ filepaths = 1] 

所以我要存儲在表中的數據進行分區,而我想刪除舊錶時,他們年紀大不如說是30天(仍然有他們的存檔)。在上面的例子中,我們假設只有那兩個event_表。如果我刪除了2011_08_30,我希望能夠知道沒有任何內容指向文件路徑'2'並因此將其刪除,但知道一行仍指向文件路徑'1'並因此保留它。

任何想法,建議等?我相信我已閱讀的一些策略(至少對於postgres和觸發器)仍然存在競爭條件,即哪個線程首先在主鍵列上鎖定了其他相關問題。

謝謝!

+0

@ Ben不知道爲什麼當刪除'events_2011_08_30'時,爲什麼還需要檢查'filepaths = 2'是否有其他值。當你使用'on delete no action'約束時,'filepaths'中的'2'不會被刪除(如果我正確理解你的需求)。 – DrColossos

回答

1

您不需要參考計數。 (你可以使用觸發器實現它,如果你真的希望它) 你想要什麼是所謂的外鍵[約束]

清理的文件路徑表的最簡單方法是使用NOT EXISTS構建體,例如

DELETE FROM filepaths fp 
WHERE NOT EXISTS (SELECT * FROM events ev where ev.file_id = fp.file_id) 
AND NOT EXISTS (SELECT * FROM events_version_xxx ev where ev.file_id = fp.file_id) 
AND NOT EXISTS (SELECT * FROM events_version_yyy ev where ev.file_id = fp.file_id) 
... 
; 

這很難看。但數據庫模型也很醜陋。

+0

嗯,我同意這種方法可行,但我們將有數千萬或數億行,這可能需要非常很長的時間才能完成......但我很感激! – Ben

+0

但真正的問題是:在路徑名錶中有一些殘留的代價是多少?我如何理解它,真正的大表是events_version_xxx表。也許只是讓它腐爛一段時間,並定期修剪它。 – wildplasser

+1

你說得對,那可能就是在星期六晚上或者我們每個月都會減少的情況。你有什麼建議讓數據庫模型不那麼「醜陋」嗎? – Ben

2

首先,我會質疑希望將數據按日期劃分到一張表上。相反,我建議在表格中列出名爲effective_date或類似的列。


在具有上filepaths引用計數而言,這可以通過多種方式來實現,但要保證代碼的封裝,我建議以下兩種方法之一...

1.存儲過程API

通過確保所有 INSERT,UPDATE和DELETE操作都是通過存儲過程,那麼你也可以封裝增量處理在filepaths上引用和減少參考計數器。因此,沒有用戶/登錄需要訪問表進行寫入活動,而只需使用存儲過程。

2.觸發器

觸發器可以在每個events表創建封裝基準計數器遞增和遞減的代碼。每當表內容被修改時,觸發器就會觸發並傳播業務邏輯的後果。

許多人害怕觸發器,因爲他們覺得他們隱藏起來,如果過度使用,可能會有複雜的交互。然而,我認爲它們非常有用。

在任何一種情況下,通過只有一個表而不是多個表來簡化所有內容。

此外,大多數SQL設計模式不會將「刪除表」視爲「業務常規」操作。在我看來,創建或刪除表格應該被視爲設計更改,而不是數據活動。

+0

那麼1個表格會很好,但爲了加快查詢速度並使刪除舊事件變得更加容易,我們必須(至少在我的理解水平上)使用分區。我們現在有單個表格,它們非常龐大,以至於要做相當簡單的事情,比如刪除特定時間以前的所有事件,或者過濾用戶界面,都需要花費很長時間....我會更多地考慮您的答案!謝謝! – Ben

+0

此外,從我與其他人的討論中,似乎大多數數據倉庫情況按日期或其他標準分區表... – Ben

+0

我已經處理了TB級大小的數據倉庫,發現數據分區更經常*不是必需的*比*要求*。我會考慮數據結構和/或索引對您正在執行的操作的適用性。另外,在使用分區時,我強烈建議*針對具有特定日期的表格;而是使用相對期間,例如「過去30天」有一張表,另一個表示「335天前」,第三個表示「之前的所有內容」(或類似),然後每晚都進行批量處理以移動數據周圍。 – MatBailie