0

還有many ActiveRecord版本控制寶石可用於Rails,但大多數(如果不是全部)都有troublebeingmaintained。最重要的是,其中一些似乎有各種各樣的foreignkeyassociationissues處理EAV模型表版本的建議

我正在對內容管理系統進行編碼,其中頁面存儲在樹狀分層結構中,頁面字段使用EAV model存儲在單獨的表格中。

記住這一點,我不是在尋找一個包羅萬象的修正寶石,因爲我真的不認爲我會找到一個。我正在尋找的是關於如何處理這個作爲自定義實現的一些建議。我應該有一個單獨的表來存儲修訂版,並在我的EAV表中引用修訂版號?我預見到這可能會導致一些複雜的驗證問題。我目前有一個問題找到一個乾淨的方式來驗證一個普通的EAV表無論如何,如果任何人都可以對此發表評論,它將非常感激。

我希望這個問題寫得足夠好,符合SO標準。如果您需要任何其他信息,請不要猶豫,我會盡力幫助您。 :)

回答

2

我現在有一個問題,找到一個乾淨的方法來驗證正 EAV表反正因此,如果任何人都可以在此發表評論,這將是非常 讚賞爲好。

不是一個乾淨的方法來驗證或者限制的EAV表。這就是DBA稱之爲anti-pattern的原因。 (EAV從幻燈片16開始。)比爾並沒有談論版本,所以我會。

版本控制看起來很簡單,但事實並非如此。要版本化一行,您可以添加一列。它是一個版本號還是一個時間戳並不重要。

create table test (
    test_id integer not null, 
    attr_ts timestamp not null default current_timestamp, 
    attr_name varchar(35) not null, 
    attr_value varchar(35) not null, 
    primary key (test_id, attr_ts, attr_name) 
); 

insert into test (test_id, attr_name, attr_value) values 
(1, 'emp_id', 1), 
(1, 'emp_name', 'Alomar, Anton'); 

select * from test; 

test_id attr_ts      attr_name attr_value 
-- 
1  2012-10-28 21:00:59.688436 emp_id  1 
1  2012-10-28 21:00:59.688436 emp_name Alomar, Anton 

雖然它在輸出上可能看起來不像它,但所有這些屬性值都是varchar(35)。 dbms沒有簡單的方法來阻止某人作爲emp_id輸入'wibble'。如果您需要類型檢查,您必須在應用程序代碼中執行此操作。 (並且你必須保持睡眠不足的DBA不使用dbms提供的命令行和GUI接口。)

對於規範化的表,當然,你只需聲明emp_id是整型。

通過版本控制,更新Anton的名字變成插入。

insert into test (test_id, attr_name, attr_value) values 
(1, 'emp_name', 'Alomar, Antonio'); 

通過版本控制,選擇過於複雜。您可以使用視圖而不是通用表格表達式。

with current_values as (
    select test_id, attr_name, max(attr_ts) cur_ver_ts 
    from test 
    -- You'll probably need an index on this pair of columns to get good performance. 
    group by test_id, attr_name 
) 
select t.test_id, t.attr_name, t.attr_value 
from test t 
inner join current_values c 
     on c.test_id = t.test_id 
     and c.attr_name = t.attr_name 
     and c.cur_ver_ts = t.attr_ts 

test_id attr_name attr_value 
-- 
1   emp_id  1 
1   emp_name Alomar, Antonio 

100萬行和8個不可爲空的列的規格化表有100萬行。一個類似的EAV表有800萬行。版本化的EAV表格有800萬行,並且每個值和每個屬性名稱的每個更改都有一行。

存儲一個版本號,並加入到包含當前值的第二個表中,如果有的話,並沒有太大的收穫。每個(傳統)插入都需要插入兩個表中。8行中的一行將成爲16行(兩個表中的每一行中都有8行)。

選擇有點簡單,只需要一個連接。

+0

感謝您的回答。抱歉沒有及時檢查。我知道這是一種反模式。我想我會做我的研究,並尋找更好的解決方案來解決我的問題。雖然很好的答案。謝謝。 –