隨筆 - 71  文章 - 15  trackbacks - 0
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          因為口渴,上帝創(chuàng)造了水;
          因為黑暗,上帝創(chuàng)造了火;
          因為我需要朋友,所以上帝讓你來到我身邊
          Click for Shaanxi xi'an, Shaanxi Forecast
          ╱◥█◣
            |田|田|
          ╬╬╬╬╬╬╬╬╬╬╬
          If only I have such a house!
          〖總在爬山 所以艱辛〗
          Email:myesjoy@yahoo.com.cn
          NickName:yesjoy
          MSN:myesjoy@hotmail.com
          QQ:150230516

          〖總在尋夢 所以苦痛〗

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          Hibernate在線

          Java友情

          Java認證

          linux經(jīng)典

          OA系統(tǒng)

          Spring在線

          Structs在線

          專家專欄

          企業(yè)信息化

          大型設備共享系統(tǒng)

          工作流

          工作流產(chǎn)品

          網(wǎng)上購書

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          4、在數(shù)據(jù)統(tǒng)計上的比較

            假設要根據(jù)EXPIRE_DATE字段,統(tǒng)計2005年每月到期的用戶數(shù)。CHAR類型日期和DATE類型日期對應的統(tǒng)計SQL語句分別分析如下。

            ·CHAR類型日期

            這種日期的表,要在日期字段上做統(tǒng)計是很方便的,下面的SQL語句統(tǒng)計出2005每月的T_USER記錄:

          select substr(EXPIRE_DATE,5,2) MONTH,count(USER_ID) from T_USER where EXPIRE_DATE like '2005%'group by substr(EXPIRE_DATE,5,2)
             表 5 CHAR類型日期統(tǒng)計SQL

            其中substr(EXPIRE_DATE,5,2)字符串處理函數(shù)獲取日期的月份,如"20060102"通過該函數(shù)即得到"01"的月份值。而"EXPIRE_DATE like '2005%'"的條件式即過濾出所有2005年的數(shù)據(jù),并且可以使用EXPIRE_DATE字段上的索引。

            ·DATE類型日期

            對于DATE類型日期按月進行統(tǒng)計,乍一看,可以采用和CHAR類型日期相似的統(tǒng)計SQL語句:

          select extract(month from EXPIRE_DATE) MONTH,count(USER_ID) from T_USER where extract(year from EXPIRE_DATE ) = 2005 group by extract(month from EXPIRE_DATE)
              表 6 DATE類型日期統(tǒng)計SQL(全表掃描)

            注:在Oracle中通過extract(<日期域名> from Date)函數(shù)獲取日期的某特定日期域仁值。

            但是仔細一分析,就會發(fā)現(xiàn)由于where條件式中對索引字段EXPIRE_DATE使用了extract()函數(shù),因此EXPIRE_DATE上的索引在此統(tǒng)計SQL中將無法使用,所以該統(tǒng)計將引發(fā)一個全表掃描。
          當然,你可以在EXPIRE_DATE字段上建立函數(shù)索引,但EXPIRE_DATE上的查詢可以不僅僅只會用到extract()函數(shù),一一為這些EXPIRE_DATE字段建立多個函數(shù)索引不但麻煩而且會影響T_USER上數(shù)據(jù)更新操作的性能。

            當然,除了上式的統(tǒng)計方法外,還可以采用另外一種方法:

          select extract(month from EXPIRE_DATE) month,count(USER_ID) from T_USER where EXPIRE_DATE between to_date('20050101','yyyymmdd') and to_date('20051231','yyyymmdd') group by extract(month from EXPIRE_DATE)
              表 7 DATE類型日期統(tǒng)計SQL(使用索引)

            表 7的方法可以使用EXPIRE_DATE字段上的索引,但又引入了一個我們前面已經(jīng)提到過的不可避免的問題:必須按日期語義構造出開始和結束日期,以形成一個日期區(qū)間。在該例中,由于是對一整年進行統(tǒng)計,因而開始結束日期容易獲得,如果是精確到月的日期區(qū)間,則需要計算出某月的最后一天,程序就復雜多了。但如果是CHAR類型日期的表,構造統(tǒng)計SQL語句,也易如反掌:如我們要統(tǒng)計200304~200402每月到期的用戶數(shù),可以通過以下SQL語句:

          select substr(EXPIRE_DATE,1,6) year_month ,count(USER_ID)from T_USER where EXPIRE_DATE between '20030400' and '20040299'group by substr(EXPIRE_DATE,1,6)

            即將開始日期以0補齊到8位,將結束日期以9補齊到8位。

           5、在數(shù)據(jù)庫移植上的比較

            由于CHAR類型日期實際上是一個字符類型字段,字符類型是最基本的數(shù)據(jù)類型,在構造Insert ,Update,Delete,Selete的SQL時,各種數(shù)據(jù)庫對字符類型字段的處理幾乎一致,因此在數(shù)據(jù)庫的移植上比較容易。

            對于DATE類型的日期,由于不同數(shù)據(jù)庫對日期的操作差異很大,如獲取數(shù)據(jù)庫的時間函數(shù),Oracle為sysdate,SqlServer為getdate(),而MySql為now();從Date字段中抽取年的數(shù)值,Oracle為extract(year from ),SqlServer和MySql均為month()。由于日期函數(shù)在不同數(shù)據(jù)庫差別巨大,帶DATE類型日期字段的表在數(shù)據(jù)庫的移植上就不如CHAR類型日期來得簡單易行。
          也許,有人會說現(xiàn)在都采用Hibernate進行映射ORM了,Hibernate已經(jīng)屏蔽了具體數(shù)據(jù)庫的不同,何來的數(shù)據(jù)庫移植?這話在一定程度上是沒有錯的,但是Hibernate框架由于通過對象映射的方法產(chǎn)生SQL語句,有時往往很難獲得最優(yōu)的查詢性能的SQL語句。所以,對于一些有性能要求較高的查詢,往往采用直接編寫SQL語句,或采用iBatis框架,后兩者都需要直接使用SQL語句,此時數(shù)據(jù)庫的移植問題就暴露出來了。

            不但在數(shù)據(jù)庫的移植問題上,CHAR類型日期比DATE類型日期擁有絕對的優(yōu)勢,在數(shù)據(jù)的導入/導出,數(shù)據(jù)傳輸?shù)确矫妫珻HAR類型日期比DATE類型日期也具有較多的優(yōu)勢。字符型的數(shù)據(jù)可以直接不失真地用文本或XML表示,而Date類型導出為文本時,如果不指定好轉(zhuǎn)換格式往往難于處理,如2001-01-01的Date數(shù)據(jù)在轉(zhuǎn)換為文本時,可能變?yōu)?st Mon 2001,也可能為2001-01-01 00:00:00 ,甚至可能是01-01-01。這樣,在導入時顯得難以操作,因為導入/導出都需要指定好日期格式。

            6、總結

            有一句很經(jīng)典的關于軟件設計的話:如果你的程序邏輯變得很復雜,也許并不是問題域本身的復雜度造成的,往往將歸因于設計上的缺陷和瑕疵。同樣一個問題,采用不同的策略,往往造成大相徑庭的解決復雜度。Spring框架功能強大,我本以為代碼一定很復雜,但是當我研讀了Spring框架的代碼時,才詫異地發(fā)現(xiàn)Spring框架的源碼很少有超過300行代碼的類,類和方法大多簡潔明了,真是應了那句大巧若拙,大道至簡的話了。

            在庫表設計時,日期字段究竟是采用CHAR類型日期還是DATE類型日期,在作出選擇時,需要考慮在程序邏輯中該數(shù)據(jù)的加工操作邏輯,畢竟表字段是需要在程序邏輯中使用和操作的,而非僅僅做一個簡單的記錄而已。
          通過上文的分析,我們發(fā)現(xiàn)CHAR類型日期可以在較大的程度上簡化程序的開發(fā),并且充分利用索引,獲取較好的性能。但又一個問題產(chǎn)生了,既然CHAR類型日期這么不好用,各數(shù)據(jù)庫又都提供了Date日期格式,是否Date數(shù)據(jù)類型就成了尸位素餐的擺設了呢?換言之,Date數(shù)據(jù)類型適合在什么場合使用呢?筆者個人的建議是,在幾乎任何時候都不要使用Date類型作為表字段類型,Date類型僅在存儲過程,數(shù)據(jù)庫函數(shù)這些數(shù)據(jù)庫程序邏輯代碼編寫場合使用,即把它看成是一個運算過程的中間工具而不要用其作數(shù)據(jù)的存儲形式。

            另外還有一個需要探討的問題,那就是Date類型長度是7,而Char(8)或Char(14)要比之浪費不少的存儲空間,其中這個問題在古代確實是一個大問題,那時候一間茅屋都要合理利用,現(xiàn)在很容易就可以得到廣廈千萬間。由于硬件性價比持續(xù)提升,也就可以使我們采用一些軟件上更簡便的方法來改善程序的設計,如Java的代碼反射,IoC的實現(xiàn)注入,XML形式的數(shù)據(jù)表示都是受惠于硬件的提升。因此,現(xiàn)在,一般而言,很微小的存儲空間占用和性能的影響并不需要設計人員特別的關注,他們要更多關注的往往是如何使邏輯簡化,如何使系統(tǒng)更具擴展性,可維護性和移植性上

          posted on 2006-10-13 13:51 ★yesjoy★ 閱讀(565) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫設計
          主站蜘蛛池模板: 延津县| 宁远县| 太和县| 墨竹工卡县| 乐清市| 河津市| 伊春市| 满洲里市| 光山县| 疏勒县| 乐清市| 济南市| 裕民县| 讷河市| 平山县| 开封市| 临朐县| 汶上县| 梨树县| 乌拉特中旗| 嘉定区| 白银市| 科技| 河池市| 宁海县| 普兰县| 太和县| 盐池县| 平南县| 三河市| 曲松县| 兴城市| 海丰县| 磐石市| 缙云县| 黔江区| 宁强县| 洛浦县| 武汉市| 新蔡县| 新巴尔虎左旗|