2014-01-05 44 views
3

我想設計一些類似於管理員定義每個表單域的動態表單。 i設計3表:MainForm的表共享屬性,然後formfield具有mainformID作爲外鍵表和定義每個表單字段 例如:分析場景性能?

AutoID | FormID | FieldName 
_____________________________ 
100 | Form1 | weight 
101 | Form1 | height 
102 | Form1 | color 
103 | Form2 | Size 
104 | Form2 | Type 
.... 

在執法機關一個formvalues表像波紋管:

FormFieldID | Value | UniqueResponseID 
___________________________________________ 
100   | 50px | 200 
101   | 60px | 200 
102   | Red | 200 

100   | 30px | 201 
101   | 20px | 201 
102   | Black | 201 


103   | 20x10 | 201 
104   | Y  | 201 
.... 

對於每種形式,我必須加入這3個表來捕捉所有字段和值。我想知道它是設計這種場景的唯一方法嗎?它會降低sql性能嗎?或者有沒有更快更好的方法?

回答

0

這是一種形式EAV,我會假設你絕對必須這樣做而不是「靜態」設計。

它會降低sql性能嗎?

是,讓一幫行(下EAV)總是會比僅僅獲得一個(靜態設計下)慢。

還是有什麼更快更好的方法?

不是從邏輯的角度來看,但是可以在物理層面上進行顯着的優化(至少對查詢性能而言)。具體來說,您可以仔細設計您的密鑰以最大限度地減少I/O(將相關數據放在一起),甚至可以消除JOIN本身。

例如:

enter image description here

這種模式通過外鍵層次遷移鍵下降到ATTRIBUTE_VALUE表的所有道路。在ATTRIBUTE_VALUE表所得到的天然複合鍵,使我們能夠:

  • 獲取所有由單個索引屬性給定形式的範圍掃描上ATTRIBUTE_VALUE表 + 表堆訪問,和根本沒有做任何JOIN。除此之外,你可以cluster 它,消除表堆訪問並留下您只用索引範圍掃描

  • 如果您只需要獲取數據以獲得特定響應,請更改組合鍵中字段的順序,以便RESPONSE_ID位於前沿。

  • 如果您需要「的形式」和「響應」的查詢,則需要兩個指標,在這一點上,我建議輔助索引也cover 價值領域。

例如:

-- Since we haven't used NONCLUSTERED clause, this is a B-tree 
-- that covers all fields. Table heap doesn't exist. 
CREATE TABLE ATTRIBUTE_VALUE (
    FORM_ID INT, 
    ATTRIBUTE_NAME VARCHAR(50), 
    RESPONSE_ID INT, 
    VALUE VARCHAR(50), 
    PRIMARY KEY (FORM_ID, ATTRIBUTE_NAME, RESPONSE_ID) 
    -- FOREIGN KEYs omitted for brevity. 
); 

-- We have included VALUE, so this B-tree covers all fields as well. 
CREATE UNIQUE INDEX ATTRIBUTE_VALUE_IE1 ON 
    ATTRIBUTE_VALUE (RESPONSE_ID, FORM_ID, ATTRIBUTE_NAME) 
    INCLUDE (VALUE); 

或特定屬性,或特定屬性的特定響應。

默認情況下,MS SQL Server會聚集所有表,除非指定了NONCLUSTERED子句。

友善聚類和消除的JOIN的一些自然鍵的主要優勢的(而不是代理鍵)。但他們也使表格「更胖」,而不是從ON UPDATE CASCADE隔離。在這個特殊情況下,我認爲專業人士勝過負面因素。有關自然與替代鍵的更多信息,請看here

幸運的是,MS SQL服務器supports包括在索引字段僅用於覆蓋目的(而不是實際通過索引搜索)。這使得索引比相同字段上的「正常」索引更精簡。

0

我喜歡Branko的方法,它與我過去創建的元數據模型很相似,所以這篇文章是通過對他的擴展。你可能想要添加一個數據類型表,它可以用於本機類型(int,varchar,bit,datetime等)和你自己的定義(儘管我沒有看到袖口的必要性)。

那裏,布蘭科的 「值」 列變爲:

value_tinyint TINYINT

value_int INT

value_varchar VARCHAR(XX)

與datatype_id(可能TINYINT )作爲外鍵加入「mydatatype」表中。

[藉口缺乏像BD漂亮的ER圖的]

mydatatype

datatype_id TINYINT

代碼VARCHAR(16)

描述VARCHAR(64) - 供參考

此擴展應該:

a。在讀取或寫入數據時爲您節省大量的鑄件

b。允許使用一些容易構建的動態SQL進行讀取和寫入。另外(也許這超出了範圍),您可能希望存儲這些對象的創建/保存順序,以及基於按鈕的條件顯示推/複選框/單選按鈕選擇等。

我不會在這裏詳細介紹,因爲我不確定你是否需要這些東西,但如果你這樣做,我會每隔一段時間檢查一次並回應一些東西。