不定字段数目的数据库表设计和数据结构
可能采用四種技術(shù):
現(xiàn)在我們來分析一下四種技術(shù)的優(yōu)劣,不過首先可以排除的是第一點(diǎn)動態(tài)增加字段的方法,因?yàn)樵趯?shí)際操作時(shí)候幾乎是不可能的(sqlserver太慢,oracle索性不支持),基本可以不討論就排除。剩下后三點(diǎn)。
先來討論預(yù)留空白字段的方法,基本原理就是在數(shù)據(jù)庫表設(shè)計(jì)的時(shí)候加入一些多余的字段,看下面的代碼:
CREATETABLESample(??name?varchar(12),????field0?varchar(1),??field1?varchar(1),????fieldN?varchar(1)}然后看實(shí)際運(yùn)行時(shí)候的需要,動態(tài)分配字段給系統(tǒng)使用,也許需要一個(gè)這樣的結(jié)構(gòu)來描述分配情況:
publicclassAvailable{??public?int?CurrentUnusedFieldNumber;??public?Hashtable?FieldToRealName;}也許某一時(shí)刻的數(shù)據(jù)狀況是這樣的: CurrentUnusedFieldNumber=3, 哈西表FieldToRealName包含內(nèi)容是("field0"="SomeId", "field1"="AnyName", "field2=IsOk")
現(xiàn)在的問題是如果要配合Hibernate,如何來處理?以上段的數(shù)據(jù)使用狀況為例子,如果我們的類定義是這樣:
publicclassEntity01{??public?string?Name;??public?string?SomeId;??public?string?AnyName;??public?bool?IsOk;}也許只需要修改一下xxx.hbm.xml,把 SomeId 和 field0 做成對應(yīng)就ok了。但是在運(yùn)行時(shí)我們怎么知道會有這樣的類定義?除非我們做動態(tài)代碼生成,自動編譯也許可以,但是問題也許就到其他方面去了;如果我們不用動態(tài)定義,那么類就只能是這樣:
publicclassEntity01{??public?string?Name;??public?Hashtable?ExtraFieldAndValues;}使用的時(shí)候,用 entity01.ExtraFieldAndValues.setValue("AnyName", "boss") 的方式來引用,也許這樣是修改最少的了,但是問題是Hibernate不支持這樣的方法。
再來討論單字段存儲的方法,我們使用這樣的數(shù)據(jù)庫表定義
CREATETABLESample(??Name?varchar(12),??Xml?CLOB(102400)?//僅作說明而已)然后對應(yīng)這樣的類定義
publicclassEntity01{??public?string?Name;??public?string?Xml;??public?Hashtable?ExtraNameAndValueFromXml;}我們的代碼就可以這樣使用:string id = entity01.ExtraNameAndValueFromXml.getValue("SomeId") 了。這樣解決看起來很不錯,不僅不需要Available表,而且看起來Hibernate對它的支持也很完美,但是致命的問題在于:如果保持高效的查詢?除非數(shù)據(jù)庫系統(tǒng)本身對此有支持,否則就只能用低效的substring或者like做查詢,這在大批量數(shù)據(jù)中根本就不可行。
是不是折衷一下,把兩種方法的優(yōu)點(diǎn)和起來?問題有來了:怎么保持兩者之間數(shù)據(jù)的同步?難道要我們用存儲過程去解析xml內(nèi)容?
所以,一個(gè)兩難的問題,需要我們認(rèn)真去解決。我們通過認(rèn)真的需求分析,也許可以減少可變字段的數(shù)量,但是只要有一個(gè)可變字段或者可變的可能性存在,我們始終要去解決這個(gè)兩難的問題。
期待繼續(xù)討論。
(新增部分)
還有一種方法就是改列為行,用另外一個(gè)表存放擴(kuò)展字段,定義可以如下:
其中idSample關(guān)聯(lián)到Sample表的id字段(我沒有寫出來)。這樣的話,Hibernate很容易支持,也可以支持Sql的查詢,而且可以支持把內(nèi)容放到Hashtable中去,看起來是目前最好的方式了。但是在大容量數(shù)據(jù)的時(shí)候,SampleFields表的數(shù)據(jù)會是主表數(shù)據(jù)量的N倍(看定制的字段數(shù)目多少而定),同樣存在有很嚴(yán)重的性能問題。
哪位高人還能再給一個(gè)方案?
---------2005-7-22新增-----------
很多朋友給出了很好的建議,其中蛙蛙池塘 給出了一個(gè)表結(jié)構(gòu),因?yàn)榭雌饋聿簧醴奖?#xff0c;我把類圖畫出來如下:
圖所表示的內(nèi)容簡單來說是這樣:
1。一個(gè)很寬的表ProductAttributeValues,包含用到的幾乎所有可能的類型的值,但是每次只能用一個(gè)類型的值
2。將可變的列轉(zhuǎn)為行,存放到上表中
3。為了存放類型定義和一些下拉列表的內(nèi)容,設(shè)計(jì)了ProductAttributeTemplates和關(guān)聯(lián)的其他表
4。ProductListItems中存放Product中所有項(xiàng)的說明和順序。
這種思路其實(shí)就是把產(chǎn)品的“知識級”(設(shè)計(jì)模式用語)和“操作級”都表現(xiàn)出來了,如果要劃分,則圖的左上角三個(gè)表屬于“操作級”,其余的屬于“知識級”。wljcan 網(wǎng)友建議我去看《設(shè)計(jì)模式》的“觀察模式”,我發(fā)現(xiàn)上圖其實(shí)就是一種和“觀察模式”相似的設(shè)計(jì)。《設(shè)計(jì)模式》看了很久都沒能看下去,不過這幾天正在看“觀察模式”,等有心得了,再來看看能不能對上圖的結(jié)構(gòu)修改一下。怡紅公子 提醒說oracle和sql server對xml字段其實(shí)已經(jīng)不錯了,所以找了一下,但是真的是既產(chǎn)品中恐怕還是不敢用,不知道性能如何。雖然采用xml方式是我最推崇的方法。而且一旦采用xml方式存儲,恐怕就會有changyu 網(wǎng)友提醒的數(shù)據(jù)類型問題,要存一個(gè)圖片的話恐怕就歇菜了(當(dāng)然也不是說xml中就一定不能存圖片)。
不過我現(xiàn)在覺得xml字段還是要的,作為輔助存儲手段,因?yàn)楫吘刮磥聿樵兤饋砜赡軙奖阈?#xff0c;然后結(jié)合“觀察模式”也就是類似上圖的方法作為主要的存儲手段,雖然有一些冗余,結(jié)合我的使用 NVelocity 解析 PowerDesigner 的cdm文件 ,工作量也不會太大。
再研究研究看看。
總結(jié)
以上是生活随笔為你收集整理的不定字段数目的数据库表设计和数据结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 物理学家(说一说物理学家的简介)
- 下一篇: 使用Gridview绑定数据库中的图片