我現在有一個問題,找到一個乾淨的方法來驗證正 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行)。
選擇有點簡單,只需要一個連接。
感謝您的回答。抱歉沒有及時檢查。我知道這是一種反模式。我想我會做我的研究,並尋找更好的解決方案來解決我的問題。雖然很好的答案。謝謝。 –