馮火:HIT數(shù)據(jù)庫表設計實踐
開始今天文章之前,請允許我先回顧前段時間在CHIMA公眾號寫了一篇文章“馮火:如何設計可以運行20年的新一代HIS系統(tǒng)”,我看到有一條留言說我的文章觀點獨到,你可能會好奇是我是怎么想到的?“攜號轉網(wǎng)”是我在別人文章里看到的,本質(zhì)是解決“用戶被運營商綁架”的問題,當時只是覺得這個了不起,沒有想到它跟我從事的HIT有什么關系。那天聽HIT專家網(wǎng)組織了“新一代醫(yī)院信息系統(tǒng)”網(wǎng)課,提到“如何打造20年不做顛覆性改變”,其中又提到廠商需要開放,我突然想到HIT最大問題是“綁架”,本質(zhì)上“攜號轉網(wǎng)”解決一樣的問題,兩件事情在我腦子里瞬間完成了碰撞,怎么可以做到“攜號轉網(wǎng)”,帶著這個疑問,繼續(xù)深思,運營商綁架的是什么,是手機號碼,HIT廠商綁架的是什么,是“醫(yī)療數(shù)據(jù)”,再逐步展開分析,就有了你們看到的文章!
言歸正傳,既然上文中提到了如何設計“數(shù)據(jù)庫”是關鍵。數(shù)據(jù)庫設計特指關系型數(shù)據(jù)庫設計,nosql不是本文所要討論的內(nèi)容。我們經(jīng)常遇到HIT表結構設計的亂糟糟(也有少數(shù)公司設計精良的),可以用一個詞來形容“隨心所欲”,有命名像天書的、沒有注釋字段都是靠猜、不加相應索引導致系統(tǒng)跑段時間突然變“龜速”、有照搬教科書設計范式等等,數(shù)據(jù)庫設計好與壞,你我心里都有一桿“秤”。
在今天大數(shù)據(jù)、人工智能非常火爆的情況下,對數(shù)據(jù)的質(zhì)量非常重視,即當下有一個火熱的詞匯“數(shù)據(jù)治理”,我寫了一篇文章“淺談數(shù)據(jù)治理”(https://www.jianshu.com/p/ee4850a9a1be),大家有興趣可以去看看。既然數(shù)據(jù)的源頭基本來自“數(shù)據(jù)庫”。怎么樣設計出一個合理的數(shù)據(jù)庫?這是一個很重要的問題,以下是根據(jù)我多年經(jīng)驗試著回答這個問題。
不合理的數(shù)據(jù)庫設計
天書般的命名。你應該見過這樣的命名(AKA01、AKA02、BAA、P1、P2等),軟件開發(fā)有句俗話“代碼即文檔”,什么意思,看你的代碼就像看你寫的文檔一樣的易懂。這樣的命名無疑增加大家的使用成本,有人說這樣做是為了數(shù)據(jù)庫安全,數(shù)據(jù)庫的安全不是靠用不規(guī)范的命名就可以解決?再強調(diào)一次,安全問題本質(zhì)非法訪問未授權的資源!這是人為造成不便利,公司開發(fā)效率低、運維效率低。
表結構與注釋分離。字段命名采用拼音縮寫的,字段的注釋沒有在一起描述,很多軟件公司不在數(shù)據(jù)庫表直接寫注釋,而是單獨用一個txt或者doc來記錄,我個人認為這是一個不好的習慣,我們經(jīng)常有這樣的困惑,寫sql的時候,突然想知道這個表這個字段是什么意思,第一種方法,靠猜,看它的記錄是什么數(shù)據(jù);第二種方法,打開公司提供的數(shù)據(jù)字典,ctrl+f查找這個字段是什么意思。或許你說這是為了技術保密,保密不是靠不寫注釋就可以保障的!這是人為造成不便利,用戶、公司的開發(fā)、運維、實施也不方便,不經(jīng)意間降低工作效率!
注釋那一列是空白
范式使用場景不對。首先了解范式的是什么,范式是用來解決數(shù)據(jù)冗余存儲的問題的,范式別級越高,冗余度越小。由于經(jīng)驗缺乏的關系,業(yè)務數(shù)據(jù)表經(jīng)常被設計成3NF,導致數(shù)據(jù)完整性受影響、增加寫sql復雜程度問題。為什么會有范式使用場景不對的,會有什么影響,后面我將舉例說明。
基礎表與業(yè)務表設計沒有充分解耦。“解耦”這個詞,大家并不陌生,在數(shù)據(jù)庫這個層面,個人認為“基礎表與業(yè)務表”需要充分解耦。這個怎么理解,表之間關系通常是一對一、一對多、多對多,問題主要出在“一對多”這種關系,我們一般在維護了“外鍵”來表達這種關系。舉例說明,“醫(yī)囑表”設計一個來自于“醫(yī)生表”外鍵,設計人員本意要表達一種“一對多”關聯(lián)關系。在實際使用過程當中會產(chǎn)生什么問題,第一個問題,業(yè)務表數(shù)據(jù)量通常是非常大,勢必增加系統(tǒng)開銷;第二個問題,假設刪除某個醫(yī)生,數(shù)據(jù)庫就會關聯(lián)業(yè)務表的外鍵報錯,業(yè)務表一般認為不可變的數(shù)據(jù)(人為后臺修改除外),影響用戶體驗。有經(jīng)驗設計者,一般去掉這個外鍵,然后在注釋當中寫明“外鍵關系”,降低基礎表與業(yè)務表耦合。
業(yè)務表設計一個來自于基礎表的外鍵
我總結的經(jīng)驗:1、業(yè)務數(shù)據(jù)表,一般設計冗余存儲,可以不加外鍵,在注釋當中說明這種“一對多”關系;2、基礎數(shù)據(jù)表,一般設計成3NF,基礎數(shù)據(jù)表之間可以加“外鍵”,遵循最小代價修改原則,后面我還會提到這個問題,因為十分重要。
關鍵字段沒有索引。這個很好理解,系統(tǒng)跑了一段時間以后,由于沒有對關鍵字段維護索引,系統(tǒng)突然變“龜速”。
我認為合理的設計
合理的命名。表、字段的命名,可以采用簡寫拼音、英語單詞、英語單詞縮寫。比方說“患者姓名”字段,可以是xm(簡寫拼音)、patient_name(英語單詞)、pat_name(英語單詞縮寫)。對于英文水平很高優(yōu)先采用英語單詞、英語單詞縮寫,對于英文差的,可以簡寫拼音,總之不要用“六親不認”的命名。
表結構與注釋一起
mysql表,外鍵描述
對于“業(yè)務數(shù)據(jù)”表結構設計,盡可能接近1NF
對于一些不經(jīng)常變動基礎的數(shù)據(jù)進行冗余保存到業(yè)務表,比如,保存“發(fā)票類別代碼+發(fā)票類別名稱”、“醫(yī)生工號+醫(yī)生姓名”、“科室代碼+科室名稱”、“結算方式+結算方式名稱”等。這樣做的目的,1、盡可能避免多表查詢,考慮效率,因為業(yè)務數(shù)據(jù)是要被經(jīng)常訪問的,能訪問一張表搞定,就不要訪問兩張表;2、保持歷史數(shù)據(jù)獨立完整性,比如,某位員工離職了,就把操作權限連同基礎數(shù)據(jù)一起刪除了,依然不影響歷史數(shù)據(jù)查詢。我們醫(yī)院就有“結算方式”被禁用,導致有些系統(tǒng)無法讀不出來歷史數(shù)據(jù)了,原因是原來在開發(fā)軟件時候,由于沒有冗余存儲,直接關聯(lián)了基礎表,導致讀不出來。
對于“基礎字典數(shù)據(jù)”表結構設計,盡可能接近3NF(盡量最小的修改代價原則)
范式級別越高,信息冗余就越小,但一般到3NF就可以,盡可能符合“盡量最小的修改代價原則”。基礎數(shù)據(jù)由于記錄少,多表查詢一般不會有執(zhí)行效率問題,數(shù)據(jù)冗余越小我們維護越方便,出錯概率就越小,系統(tǒng)穩(wěn)定性高。
基礎表與業(yè)務表設計之間耦合問題,上文已經(jīng)提及解決方案,在此不再贅述。關鍵字段沒有索引問題,有時候需要專業(yè)的DBA來維護,在此不再贅述。
回顧理論知識
為了考慮廣大讀者的實際情況,更好理解文中所描述的內(nèi)容,我還是把重要的理論知識跟大家簡單回顧一下。
第一范式(1NF)指字段是否為復合字段,不可拆分,這個要看業(yè)務情況,比如姓名字段,你要不要拆分成“姓”、“名”2個字段。“地址”要不要拆分省市、縣、街道。
第二范式(2NF)在1NF基礎上,非主屬性字段之間消除部分或完全依賴(另一種說法非主屬性完成依賴于主鍵)。舉例說明,非主屬性數(shù)量、單價、金額之間存在依賴關系。
部分依賴
第三范式(3NF)在2NF基礎上,非主屬性字段之間消除傳遞依賴。舉例說明,出生日期、年齡、是否成人,存在傳遞依賴。
傳遞依賴
"一對多"關系,一般在“多”的一方,維護一個“外鍵”表達這種關系。
一對多
"多對多"關系,使用中間表表達這種關系。
多對多
患者主索引設計實戰(zhàn)(含視頻)
(作者:廣東省羅定市人民醫(yī)院信息科 馮火)
CHIMA大講堂第一期回放:
https://live.chima.org.cn/watch/975050
CHIMA大講堂第二期回放:
https://live.chima.org.cn/watch/997828
CHIMA大講堂第三期回放:
https://live.chima.org.cn/watch/1093145
HIT企業(yè)戰(zhàn)疫——醫(yī)院信息化產(chǎn)品和服務信息查詢