2013-07-15 33 views
0

我正在爲商店,產品,客戶,供應商和倉庫等實體設計數據庫。該數據庫將用作不同實體商店中的在線交易系統。我應該將EAV值放在數據類型表中嗎?

就我而言,商店,客戶,供應商和倉庫的所有屬性都可以定義爲列,因爲它們不會隨時間變化很多。然而,產品具有無限的屬性,所以我想將這些數據放在EAV模型中。

可有人指出,如果值應在自己特定的數據類型,表把(如attribute_values_int,或由於性能原因,在通用ATTRIBUTE_VALUE表列的Magento已經選擇特定的數據類型,值表見?: http://blog.magestore.com/2012/03/23/magento-certificate-eav-model-concepts

感謝。

+0

糾正我,如果我錯了,但如果你發佈一個鏈接,說明*性能*原因magento使用類型特定的表..不是明顯的答案嗎?如果您不使用特定於類型的表格,則最終將所有內容添加到varchar/text列。如果你這樣做,你需要一個元數據表來解釋屬性的存儲位置(在int,float,char表中)。 –

+0

@ N.B。感謝您的評論,但我也可以創建具有不同列的值表(value_int,value_datetime等)。我希望你能解釋爲什麼特定數據類型選項會帶來更好的性能,至少在Magento的情況下? – Hans

+0

因爲如果使用特定於數據類型的表,並且可以將某些數據類型表編入索引,那麼將節省更多空間。這不是一個性能增益,因爲它可以放寬需要擔心屬性是否適合值列。想象一下,有一個EAV設計有1個值表,並且您正在存儲可以是單個1位數字或大量文本的數據。你被迫使用'text'類型,所以你可以存儲任何東西。或者你可以創建一個特定類型的表,不用擔心「全部捕捉」表,它是存儲值的列。 –

回答

2

坦率地說,最好的選擇是 「不EAV」。考慮使用hstore領域,XML,或json

在PostgreSQL沒有性能優勢,使用每數據類型表。 NULL值存儲在一個緊湊的NULL位圖中,所以它與你是否有像(NULL, NULL, NULL, 42, NULL, NULL)(42)這樣的元組沒有多大區別。

這也允許你添加CHECK約束實施,確切地說一個字段必須是非NULL,所以你不會得到不同類型的多個值。

演示:

regress=> CREATE TABLE eav_ugh (
    entity_id integer, 
    int_value integer, 
    numeric_value numeric, 
    text_value text, 
    timestamp_value timestamp with time zone, 
    CONSTRAINT only_one_non_null CHECK (
      (int_value IS NOT NULL AND numeric_value IS NULL AND text_value IS NULL AND timestamp_value IS NULL) OR 
      (int_value IS NULL AND numeric_value IS NOT NULL AND text_value IS NULL AND timestamp_value IS NULL) OR 
      (int_value IS NULL AND numeric_value IS NULL AND text_value IS NOT NULL AND timestamp_value IS NULL) OR 
      (int_value IS NULL AND numeric_value IS NULL AND text_value IS NULL AND timestamp_value IS NOT NULL) 
    ) 
); 
CREATE TABLE 
regress=> insert into eav_ugh (entity_id, numeric_value) select x, x from generate_series(1,5000) x; 
INSERT 0 5000 
regress=> select pg_relation_size('eav_ugh');           
pg_relation_size 
------------------ 
      229376 
(1 row) 

regress=> CREATE TABLE no_null_cols(entity_id integer, numeric_value numeric); 
CREATE TABLE 
regress=> insert into no_null_cols (entity_id, numeric_value) select x, x from generate_series(1,5000) x; 
INSERT 0 5000 
regress=> select pg_relation_size('no_null_cols'); 
pg_relation_size 
------------------ 
      229376 
(1 row) 

regress=> SELECT sum(pg_column_size(eav_ugh)) FROM eav_ugh; 
    sum 
-------- 
164997 
(1 row) 

regress=> SELECT sum(pg_column_size(no_null_cols)) FROM no_null_cols; 
    sum 
-------- 
164997 
(1 row) 

在這種情況下,零位不會由於對齊要求增加任何空間可言,有可能。

+0

謝謝指出克雷格。將所有值列放在單個表中時,是否可以在不檢查數據類型的情況下執行select?這樣數據庫返回非空列值?如果可能的話,我可以想象這比先檢查數據類型要快得多。當然,我們會在選擇包含日期計算的行時遇到問題。 – Hans

+0

@Hans:不,它不是;這是我討厭EAV並且更喜歡使用諸如hstore,json或xml字段之類的許多原因之一。 –

+0

好吧,我必須研究hstore,xml和json的可能性,因爲我的屬性鏈接到配置表。我不知道這是否可能。 – Hans

相關問題