数据库建立索引、数据表创建规则、备用字段 / 保留字段 / 预留字段
生活随笔
收集整理的這篇文章主要介紹了
数据库建立索引、数据表创建规则、备用字段 / 保留字段 / 预留字段
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
數據庫建立索引
數據庫、數據表建立索引的原則 數據庫建立索引的原則 1,確定針對該表的操作是大量的查詢操作還是大量的增刪改操作。 2,嘗試建立索引來幫助特定的查詢。檢查自己的sql語句,為那些頻繁在where子句中出現的字段建立索引。 3,嘗試建立復合索引來進一步提高系統性能。修改復合索引將消耗更長時間,同時,復合索引也占磁盤空間。 4,對于小型的表,建立索引可能會影響性能 5,應該避免對具有較少值的字段進行索引。 6,避免選擇大型數據類型的列作為索引。 索引建立的原則 索引查詢是數據庫中重要的記錄查詢方法,要不要進入索引以及在那些字段上建立索引都要和實際數據庫系統的查詢要求結合來考慮,下面給出實際中的一些通用的原則: 1. 在經常用作過濾器的字段上建立索引; 2. 在SQL語句中經常進行GROUP BY、ORDER BY的字段上建立索引; 3. 在不同值較少的字段上不必要建立索引,如性別字段; 4. 對于經常存取的列避免建立索引; 5. 用于聯接的列(主健/外健)上建立索引; 6. 在經常存取的多個列上建立復合索引,但要注意復合索引的建立順序要按照使用的頻度來確定; 7. 缺省情況下建立的是非簇集索引,但在以下情況下最好考慮簇集索引,如:含有有限數目(不是很少)唯一的列;進行大范圍的查詢;充分的利用索引可以減少表掃描I/0的次數,有效的避免對整表的搜索。當然合理的索引要建立在對各種查詢的分析和預測中,也取決于DBA的所設計的數據庫結構。 ------------------------------------------------------------------------------ 這是你的表結構,有三個字段,分別是id,name,cid CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`cid` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `name_cid_INX` (`name`,`cid`), ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 索引方面:id是主鍵,(name,cid)是一個多列索引。 ----------------------------------------------------------------------------- 下面是你有疑問的兩個查詢:EXPLAIN SELECT * FROM student WHERE cid=1;EXPLAIN SELECT * FROM student WHERE cid=1 AND name='小紅';你的疑問是:sql查詢用到索引的條件是必須要遵守最左前綴原則,為什么上面兩個查詢還能用到索引? ---------------------------------------------------------------------------------------------------------------------------講上面問題之前,我先補充一些知識,因為我覺得你對索引理解是狹隘的: 上述你的兩個查詢的explain結果中顯示用到索引的情況類型是不一樣的。,可觀察explain結果中的type字段。你的查詢中分別是: 1. type: index 2. type: ref解釋: index:這種類型表示是mysql會對整個該索引進行掃描。要想用到這種類型的索引,對這個索引并無特別要求,只要是索引,或者某個復合索引的一部分,mysql都可能會采用index類型的方式掃描。但是呢,缺點是效率不高,mysql會從索引中的第一個數據一個個的查找到最后一個數據,直到找到符合判斷條件的某個索引。所以:對于你的第一條語句: EXPLAIN SELECT * FROM student WHERE cid=1; 判斷條件是cid=1,而cid是(name,cid)復合索引的一部分,沒有問題,可以進行index類型的索引掃描方式。explain顯示結果使用到了索引,是index類型的方式。---------------------------------------------------------------------------------------------------------------------------ref:這種類型表示mysql會根據特定的算法快速查找到某個符合條件的索引,而不是會對索引中每一個數據都進行一 一的掃描判斷,也就是所謂你平常理解的使用索引查詢會更快的取出數據。而要想實現這種查找,索引卻是有要求的,要實現這種能快速查找的算法,索引就要滿足特定的數據結構。簡單說,也就是索引字段的數據必須是有序的,才能實現這種類型的查找,才能利用到索引。有些了解的人可能會問,索引不都是一個有序排列的數據結構么。不過答案說的還不夠完善,那只是針對單個索引,而復合索引的情況有些同學可能就不太了解了。下面就說下復合索引: 以該表的(name,cid)復合索引為例,它內部結構簡單說就是下面這樣排列的:mysql創建復合索引的規則是首先會對復合索引的最左邊的,也就是第一個name字段的數據進行排序,在第一個字段的排序基礎上,然后再對后面第二個的cid字段進行排序。其實就相當于實現了類似 order by name cid這樣一種排序規則。 所以:第一個name字段是絕對有序的,而第二字段就是無序的了。所以通常情況下,直接使用第二個cid字段進行條件判斷是用不到索引的,當然,可能會出現上面的使用index類型的索引。這就是所謂的mysql為什么要強調最左前綴原則的原因。那么什么時候才能用到呢? 當然是cid字段的索引數據也是有序的情況下才能使用咯,什么時候才是有序的呢?觀察可知,當然是在name字段是等值匹配的情況下,cid才是有序的。發現沒有,觀察兩個name名字為 c 的cid字段是不是有序的呢。從上往下分別是4 5。 這也就是mysql索引規則中要求復合索引要想使用第二個索引,必須先使用第一個索引的原因。(而且第一個索引必須是等值匹配)。 --------------------------------------------------------------------------------------------------------------------------- 所以對于你的這條sql查詢: EXPLAIN SELECT * FROM student WHERE cid=1 AND name='小紅'; 沒有錯,而且復合索引中的兩個索引字段都能很好的利用到了!因為語句中最左面的name字段進行了等值匹配,所以cid是有序的,也可以利用到索引了。你可能會問:我建的索引是(name,cid)。而我查詢的語句是cid=1 AND name='小紅'; 我是先查詢cid,再查詢name的,不是先從最左面查的呀?好吧,我再解釋一下這個問題:首先可以肯定的是把條件判斷反過來變成這樣 name='小紅' and cid=1; 最后所查詢的結果是一樣的。 那么問題產生了?既然結果是一樣的,到底以何種順序的查詢方式最好呢?所以,而此時那就是我們的mysql查詢優化器該登場了,mysql查詢優化器會判斷糾正這條sql語句該以什么樣的順序執行效率最高,最后才生成真正的執行計劃。所以,當然是我們能盡量的利用到索引時的查詢順序效率最高咯,所以mysql查詢優化器會最終以這種順序進行查詢執行。 --------------------------------------------------------------------------- 索引創建規則:1、表的主鍵、外鍵必須有索引;2、數據量超過300的表應該有索引; 3、經常與其他表進行連接的表,在連接字段上應該建立索引4、經常出現在Where子句中的字段,特別是大表的字段,應該建立索引;5、索引應該建在選擇性高的字段上; 6、索引應該建在小字段上,對于大的文本字段甚至超長字段,不要建索引;7、復合索引的建立需要進行仔細分析;盡量考慮用單字段索引代替: A、正確選擇復合索引中的主列字段,一般是選擇性較好的字段;B、復合索引的幾個字段是否經常同時以AND方式出現在Where子句中?單字段查詢是否極少甚至沒有?如果是, 則可以建立復合索引;否則考慮單字段索引; C、如果復合索引中包含的字段經常單獨出現在Where子句中,則分解為多個單字段索引;D、如果復合索引所包含的字段超過3個,那么仔細考慮其必要性,考慮減少復合的字段;E、如果既有單字段索引,又有這幾個字段上的復合索引,一般可以刪除復合索引;8、頻繁進行數據操作的表,不要建立太多的索引;9、刪除無用的索引,避免對執行計劃造成負面影響; 以上是一些普遍的建立索引時的判斷依據。 一言以蔽之,索引的建立必須慎重,對每個索引的必要性都應該經過仔細分析,要有建立的依據。 因為太多的索引與不充分、不正確的索引對性能都毫無益處:在表上建立的每個索引都會增加存儲開銷, 索引對于插入、刪除、更新操作也會增加處理上的開銷。另外,過多的復合索引,在有單字段索引的情況下, 一般都是沒有存在價值的;相反,還會降低數據增加刪除時的性能,特別是對頻繁更新的表來說,負面影響更大。 oracle的索引陷阱 一個表中有幾百萬條數據,對某個字段加了索引,但是查詢時性能并沒有什么提高,這主要可能是oracle的索引限制造成的。 oracle的索引有一些索引限制,在這些索引限制發生的情況下,即使已經加了索引,oracle還是會執行一次全表掃描,查詢的性能不會比不加索引有所提高,反而可能由于數據庫維護索引的系統開銷造成性能更差。 下面是一些常見的索引限制問題。1、使用不等于操作符(<>, !=) 下面這種情況,即使在列dept_id有一個索引,查詢語句仍然執行一次全表掃描 select * from dept where staff_num <> 1000; 但是開發中的確需要這樣的查詢,難道沒有解決問題的辦法了嗎? 有! 通過把用 or 語法替代不等號進行查詢,就可以使用索引,以避免全表掃描:上面的語句改成下面這樣的,就可以使用索引了。 select * from dept shere staff_num < 1000 or dept_id > 1000; 2、使用 is null 或 is not null 使用 is null 或is nuo null也會限制索引的使用,因為數據庫并沒有定義null值。如果被索引的列中有很多null,就不會使用這個索引(除非索引是一個位圖索引,關于位圖索引,會在以后的blog文章里做詳細解釋)。在sql語句中使用null會造成很多麻煩。 解決這個問題的辦法就是:建表時把需要索引的列定義為非空(not null)3、使用函數 如果沒有使用基于函數的索引,那么where子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引。下面的查詢就不會使用索引: select * from staff where trunc(birthdate) = '01-MAY-82'; 但是把函數應用在條件上,索引是可以生效的,把上面的語句改成下面的語句,就可以通過索引進行查找。 select * from staff where birthdate < (to_date('01-MAY-82') + 0.9999); 4、比較不匹配的數據類型 比較不匹配的數據類型也是難于發現的性能問題之一。 下面的例子中,dept_id是一個varchar2型的字段,在這個字段上有索引,但是下面的語句會執行全表掃描。 select * from dept where dept_id = 900198; 這是因為oracle會自動把where子句轉換成to_number(dept_id)=900198,就是3所說的情況,這樣就限制了索引的使用。 把SQL語句改為如下形式就可以使用索引 select * from dept where dept_id = '900198';二,各種索引使用場合及建議(1)B*Tree索引。常規索引,多用于oltp系統,快速定位行,應建立于高cardinality列(即列的唯一值除以行數為一個很大的值,存在很少的相同值)。Create index indexname on tablename(columnname[columnname...])(2)反向索引。B*Tree的衍生產物,應用于特殊場合,在ops環境加序列增加的列上建立,不適合做區域掃描。Create index indexname on tablename(columnname[columnname...]) reverse(3)降序索引。B*Tree的衍生產物,應用于有降序排列的搜索語句中,索引中儲存了降序排列的索引碼,提供了快速的降序搜索。Create index indexname on tablename(columnname DESC[columnname...])(4)位圖索引。位圖方式管理的索引,適用于OLAP(在線分析)和DSS(決策處理)系統,應建立于低cardinality列, 適合集中讀取,不適合插入和修改,提供比B*Tree索引更節省的空間。Create BITMAP index indexname on tablename(columnname[columnname...])在實際應用中,如果某個字段的值需要頻繁更新,那么就不適合在它上面創建位圖索引。 在位圖索引中,如果你更新或插入其中一條數值為N的記錄, 那么相應表中數值為N的記錄(可能成百上千條)全部被Oracle鎖定, 這就意味著其它用戶不能同時更新這些數值為N的記錄,其它用戶必須要等第一個用戶提交后, 才能獲得鎖,更新或插入數據,bitmap index它主要用于決策支持系統或靜態數據。(5)函數索引。B*Tree的衍生產物,應用于查詢語句條件列上包含函數的情況, 索引中儲存了經過函數計算的索引碼值。可以在不修改應用程序的基礎上能提高查詢效率。索引創建策略 1.導入數據后再創建索引 2.不需要為很小的表創建索引 3.對于取值范圍很小的字段(比如性別字段)應當建立位圖索引 4.限制表中的索引的數目 5.為索引設置合適的PCTFREE值 6.存儲索引的表空間最好單獨設定唯一索引和不唯一索引都只是針對B樹索引而言. Oracle最多允許包含32個字段的復合索引 由此估計出一個查詢如果使用某個索引會需要讀入的數據塊塊數。 需要讀入的數據塊越多,則 cost 越大,Oracle 也就越有可能不選擇使用 index三,能用唯一索引,一定用唯一索引 能加非空,就加非空約束 一定要統計表的信息,索引的信息,柱狀圖的信息。 聯合索引的順序不同,影響索引的選擇,盡量將值少的放在前面 只有做到以上四點,數據庫才會正確的選擇執行計劃。====================================================================================================================================一、 ROWID的概念存儲了row在數據文件中的具體位置:64位編碼的數據,A-Z, a-z, 0-9, +, 和 /,row在數據塊中的存儲方式SELECT ROWID, last_name FROM hr.employees WHERE department_id = 20;比如:OOOOOOFFFBBBBBBRRROOOOOO:data object number, 對應dba_objects.data_object_idFFF:file#, 對應v$datafile.file#BBBBBB:block#RRR:row#Dbms_rowid包SELECT dbms_rowid.rowid_block_number('AAAGFqAABAAAIWEAAA') from dual;具體到特定的物理文件二、 索引的概念1、 類似書的目錄結構2、 Oracle 的“索引”對象,與表關聯的可選對象,提高SQL查詢語句的速度3、 索引直接指向包含所查詢值的行的位置,減少磁盤I/O4、 與所索引的表是相互獨立的物理結構5、 Oracle 自動使用并維護索引,插入、刪除、更新表后,自動更新索引6、 語法:CREATE INDEX index ON table (column[, column]...);7、 B-tree結構(非bitmap):[一]了解索引的工作原理:表:emp目標:查詢Frank的工資salary建立索引:create index emp_name_idx on emp(name);[試驗]測試索引的作用:1. 運行/rdbms/admin/utlxplan 腳本2. 建立測試表create table t as select * from dba_objects;insert into t select * from t;create table indextableas select rownum id,owner,object_name,subobject_name,object_id,data_object_id,object_type,createdfrom t;3. set autotrace trace explain4. set timing on5. 分析表,可以得到cost6. 查詢 object_name=’DBA_INDEXES’7. 在object_name列上建立索引8. 再查詢三、 唯一索引1、 何時創建:當某列任意兩行的值都不相同2、 當建立Primary Key(主鍵)或者Unique constraint(唯一約束)時,唯一索引將被自動建立3、 語法:CREATE UNIQUE INDEX index ON table (column);4、 演示四、 組合索引1、 何時創建:當兩個或多個列經常一起出現在where條件中時,則在這些列上同時創建組合索引2、 組合索引中列的順序是任意的,也無需相鄰。但是建議將最頻繁訪問的列放在列表的最前面3、 演示(組合列,單獨列)五、 位圖索引1、 何時創建:列中有非常多的重復的值時候。例如某列保存了 “性別”信息。Where 條件中包含了很多OR操作符。較少的update操作,因為要相應的跟新所有的bitmap2、 結構:位圖索引使用位圖作為鍵值,對于表中的每一數據行位圖包含了TRUE(1)、FALSE(0)、或NULL值。3、 優點:位圖以一種壓縮格式存放,因此占用的磁盤空間比標準索引要小得多4、 語法:CREATE BITMAP INDEX index ON table (column[, column]...);5、 掩飾:create table bitmaptable as select * from indextable where owner in('SYS','PUBLIC');分析,查找,建立索引,查找六、 基于函數的索引1、 何時創建:在WHERE條件語句中包含函數或者表達式時2、 函數包括:算數表達式、PL/SQL函數、程序包函數、SQL函數、用戶自定義函數。3、 語法:CREATE INDEX index ON table (FUNCTION(column));4、 演示必須要分析表,并且query_rewrite_enabled=TRUE或者使用提示/*+ INDEX(ic_index)*/七、 反向鍵索引目的:比如索引值是一個自動增長的列:多個用戶對集中在少數塊上的索引行進行修改,容易引起資源的爭用,比如對數據塊的等待。此時建立反向索引。性能問題:語法:重建為標準索引:反之不行八、 鍵壓縮索引比如表landscp的數據如下:site feature jobBritten Park, Rose Bed 1, PruneBritten Park, Rose Bed 1, MulchBritten Park, Rose Bed 1,SprayBritten Park, Shrub Bed 1, MulchBritten Park, Shrub Bed 1, WeedBritten Park, Shrub Bed 1, Hoe……查詢時,以上3列均在where條件中同時出現,所以建立基于以上3列的組合索引。但是發現重復值很多,所以考慮壓縮特性。Create index zip_idxon landscp(site, feature, job)compress 2;將索引項分成前綴(prefix)和后綴(postfix)兩部分。前兩項被放置到前綴部分。Prefix 0: Britten Park, Rose Bed 1Prefix 1: Britten Park, Shrub Bed 1實際所以的結構為:0 Prune0 Mulch0 Spray1 Mulch1 Weed1 Hoe特點:組合索引的前綴部分具有非選擇性時,考慮使用壓縮。減少I/O,增加性能。九、 索引組織表(IOT)將表中的數據按照索引的結構存儲在索引中,提高查詢速度。犧牲插入更新的性能,換取查詢性能。通常用于數據倉庫,提供大量的查詢,極少的插入修改工作。必須指定主鍵。插入數據時,會根據主鍵列進行B樹索引排序,寫入磁盤。十、 分區索引簇:A cluster is a group of tables that share the same data blocks because they share common columns and are often used together.====================================================================================================================================為什么要創建索引呢?這是因為,創建索引可以大大提高系統的性能。 第一,通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。 第二,可以大大加快 數據的檢索速度,這也是創建索引的最主要的原因。 第三,可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。 第四,在使用分組和排序 子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。 第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。 也許會有人要問:增加索引有如此多的優點,為什么不對表中的每一個列創建一個索引呢?這種想法固然有其合理性,然而也有其片面性。雖然,索引有許多優點, 但是,為表中的每一個列都增加索引,是非常不明智的。這是因為,增加索引也有許多不利的一個方面。 第一,創建索引和維護索引要耗費時間,這種時間隨著數據 量的增加而增加。 第二,索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。 第三,當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。 索引是建立在數據庫表中的某些列的上面。因此,在創建索引的時候,應該仔細考慮在哪些列上可以創建索引,在哪些列上不能創建索引。一般來說,應該在這些列 上創建索引,例如: 在經常需要搜索的列上,可以加快搜索的速度; 在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構; 在經常用在連接的列上,這 些列主要是一些外鍵,可以加快連接的速度; 在經常需要根據范圍進行搜索的列上創建索引,因為索引已經排序,其指定的范圍是連續的; 在經常需要排序的列上創 建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間; 在經常使用在WHERE子句中的列上面創建索引,加快條件的判斷速度。 同樣,對于有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點: 第一,對于那些在查詢中很少使用或者參考的列不應該創建索引。這是因 為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統的維護速度和增大了空間需求。 第二,對于那 些只有很少數據值的列也不應該增加索引。這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比 例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。 第三,對于那些定義為text, image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要么相當大,要么取值很少。 第四,當修改性能遠遠大于檢索性能時,不應該創建索 引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因 此,當修改性能遠遠大于檢索性能時,不應該創建索引。 創建索引的方法和索引的特征 創建索引的方法 創建索引有多種方法,這些方法包括直接創建索引的方法和間接創建索引的方法。直接創建索引,例如使用CREATE INDEX語句或者使用創建索引向導,間接創建索引,例如在表中定義主鍵約束或者唯一性鍵約束時,同時也創建了索引。雖然,這兩種方法都可以創建索引,但是,它們創建索引的具體內容是有區別的。 使用CREATE INDEX語句或者使用創建索引向導來創建索引,這是最基本的索引創建方式,并且這種方法最具有柔性,可以定制創建出符合自己需要的索引。在使用這種方式創建索引時,可以使用許多選項,例如指定數據頁的充滿度、進行排序、整理統計信息等,這樣可以優化索引。使用這種方法,可以指定索引的類型、唯一性和復合性,也就是說,既可以創建聚簇索引,也可以創建非聚簇索引,既可以在一個列上創建索引,也可以在兩個或者兩個以上的列上創建索引。 通過定義主鍵約束或者唯一性鍵約束,也可以間接創建索引。主鍵約束是一種保持數據完整性的邏輯,它限制表中的記錄有相同的主鍵記錄。在創建主鍵約束時,系統自動創建了一個唯一性的聚簇索引。雖然,在邏輯上,主鍵約束是一種重要的結構,但是,在物理結構上,與主鍵約束相對應的結構是唯一性的聚簇索引。換句話說,在物理實現上,不存在主鍵約束,而只存在唯一性的聚簇索引。同樣,在創建唯一性鍵約束時,也同時創建了索引,這種索引則是唯一性的非聚簇索引。因此,當使用約束創建索引時,索引的類型和特征基本上都已經確定了,由用戶定制的余地比較小。 當在表上定義主鍵或者唯一性鍵約束時,如果表中已經有了使用CREATE INDEX語句創建的標準索引時,那么主鍵約束或者唯一性鍵約束創建的索引覆蓋以前創建的標準索引。也就是說,主鍵約束或者唯一性鍵約束創建的索引的優先級高于使用CREATE INDEX語句創建的索引。 索引的特征 索引有兩個特征,即唯一性索引和復合索引。 唯一性索引保證在索引列中的全部數據是唯一的,不會包含冗余數據。如果表中已經有一個主鍵約束或者唯一性鍵約束,那么當創建表或者修改表時,SQL Server自動創建一個唯一性索引。然而,如果必須保證唯一性,那么應該創建主鍵約束或者唯一性鍵約束,而不是創建一個唯一性索引。當創建唯一性索引時,應該認真考慮這些規則:當在表中創建主鍵約束或者唯一性鍵約束時,SQL Server自動創建一個唯一性索引;如果表中已經包含有數據,那么當創建索引時,SQL Server檢查表中已有數據的冗余性;每當使用插入語句插入數據或者使用修改語句修改數據時,SQL Server檢查數據的冗余性:如果有冗余值,那么SQL Server取消該語句的執行,并且返回一個錯誤消息;確保表中的每一行數據都有一個唯一值,這樣可以確保每一個實體都可以唯一確認;只能在可以保證實體完整性的列上創建唯一性索引,例如,不能在人事表中的姓名列上創建唯一性索引,因為人們可以有相同的姓名。 復合索引就是一個索引創建在兩個列或者多個列上。在搜索時,當兩個或者多個列作為一個關鍵值時,最好在這些列上創建復合索引。當創建復合索引時,應該考慮這些規則:最多可以把16個列合并成一個單獨的復合索引,構成復合索引的列的總長度不能超過900字節,也就是說復合列的長度不能太長;在復合索引中,所有的列必須來自同一個表中,不能跨表建立復合列;在復合索引中,列的排列順序是非常重要的,因此要認真排列列的順序,原則上,應該首先定義最唯一的列,例如在(COL1,COL2)上的索引與在(COL2,COL1)上的索引是不相同的,因為兩個索引的列的順序不同;為了使查詢優化器使用復合索引,查詢語句中的WHERE子句必須參考復合索引中第一個列;當表中有多個關鍵列時,復合索引是非常有用的;使用復合索引可以提高查詢性能,減少在一個表中所創建的索引數量。---索引的類型 根據索引的順序與數據表的物理順序是否相同,可以把索引分成兩種類型。一種是數據表的物理順序與索引順序相同的聚簇索引,另一種是數據表的物理順序與索引順序不相同的非聚簇索引。 聚簇索引的體系結構 索引的結構類似于樹狀結構,樹的頂部稱為葉級,樹的其它部分稱為非葉級,樹的根部在非葉級中。同樣,在聚簇索引中,聚簇索引的葉級和非葉級構成了一個樹狀結構,索引的最低級是葉級。在聚簇索引中,表中的數據所在的數據頁是葉級,在葉級之上的索引頁是非葉級,索引數據所在的索引頁是非葉級。在聚簇索引中,數據值的順序總是按照升序排列。 應該在表中經常搜索的列或者按照順序訪問的列上創建聚簇索引。當創建聚簇索引時,應該考慮這些因素:每一個表只能有一個聚簇索引,因為表中數據的物理順序只能有一個;表中行的物理順序和索引中行的物理順序是相同的,在創建任何非聚簇索引之前創建聚簇索引,這是因為聚簇索引改變了表中行的物理順序,數據行按照一定的順序排列,并且自動維護這個順序;關鍵值的唯一性要么使用UNIQUE關鍵字明確維護,要么由一個內部的唯一標識符明確維護,這些唯一性標識符是系統自己使用的,用戶不能訪問;聚簇索引的平均大小大約是數據表的百分之五,但是,實際的聚簇索引的大小常常根據索引列的大小變化而變化;在索引的創建過程中,SQL Server臨時使用當前數據庫的磁盤空間,當創建聚簇索引時,需要1.2倍的表空間的大小,因此,一定要保證有足夠的空間來創建聚簇索引。 當系統訪問表中的數據時,首先確定在相應的列上是否存在有索引和該索引是否對要檢索的數據有意義。如果索引存在并且該索引非常有意義,那么系統使用該索引訪問表中的記錄。系統從索引開始瀏覽到數據,索引瀏覽則從樹狀索引的根部開始。從根部開始,搜索值與每一個關鍵值相比較,確定搜索值是否大于或者等于關鍵值。這一步重復進行,直到碰上一個比搜索值大的關鍵值,或者該搜索值大于或者等于索引頁上所有的關鍵值為止。 非聚簇索引的體系結構 非聚簇索引的結構也是樹狀結構,與聚簇索引的結構非常類似,但是也有明顯的不同。 在非聚簇索引中,葉級僅包含關鍵值,而沒有包含數據行。非聚簇索引表示行的邏輯順序。 非聚簇索引有兩種體系結構:一種體系結構是在沒有聚簇索引的表上創建非聚簇索引,另一種體系結構是在有聚簇索引的表上創建非聚簇索引。 如果一個數據表中沒有聚簇索引,那么這個數據表也稱為數據堆。當非聚簇索引在數據堆的頂部創建時,系統使用索引頁中的行標識符指向數據頁中的記錄。行標識符存儲了數據所在位置的信息。數據堆是通過使用索引分配圖(IAM)頁來維護的。IAM頁包含了數據堆所在簇的存儲信息。在系統表sysindexes 中,有一個指針指向了與數據堆相關的第一個IAM頁。系統使用IAM頁在數據堆中瀏覽和尋找可以插入新的記錄行的空間。這些數據頁和在這些數據頁中的記錄沒有任何的順序并且也沒有鏈接在一起。在這些數據頁之間的唯一的連接是IAM中記錄的順序。當在數據堆上創建了非聚簇索引時,葉級中包含了指向數據頁的行標識符。行標識符指定記錄行的邏輯順序,由文件ID、頁號和行ID組成。這些行的標識符維持唯一性。非聚簇索引的葉級頁的順序不同于表中數據的物理順序。這些關鍵值在葉級中以升序維持。 當非聚簇索引創建在有聚簇索引的表上的時候,系統使用索引頁中的指向聚簇索引的聚簇鍵。聚簇鍵存儲了數據的位置信息。如果某一個表有聚簇索引,那么非聚簇索引的葉級包含了映射到聚簇鍵的聚簇鍵值,而不是映射到物理的行標識符。當系統訪問有非聚簇索引的表中數據時,并且這種非聚簇索引創建在聚簇索引上,那么它首先從非聚簇索引來找到指向聚簇索引的指針,然后通過使用聚簇索引來找到數據。 當需要以多種方式檢索數據時,非聚簇索引是非常有用的。當創建非聚簇索引時,要考慮這些情況:在缺省情況下,所創建的索引是非聚簇索引;在每一個表上面,可以創建不多于249個非聚簇索引,而聚簇索引最多只能有一個。 系統如何訪問表中的數據 一般地,系統訪問數據庫中的數據,可以使用兩種方法:表掃描和索引查找。第一種方法是表掃描,就是指系統將指針放置在該表的表頭數據所在的數據頁上,然后按照數據頁的排列順序,一頁一頁地從前向后掃描該表數據所占有的全部數據頁,直至掃描完表中的全部記錄。在掃描時,如果找到符合查詢條件的記錄,那么就將這條記錄挑選出來。最后,將全部挑選出來符合查詢語句條件的記錄顯示出來。第二種方法是使用索引查找。索引是一種樹狀結構,其中存儲了關鍵字和指向包含關鍵字所在記錄的數據頁的指針。當使用索引查找時,系統沿著索引的樹狀結構,根據索引中關鍵字和指針,找到符合查詢條件的的記錄。最后,將全部查找到的符合查詢語句條件的記錄顯示出來。 在SQL Server中,當訪問數據庫中的數據時,由SQL Server確定該表中是否有索引存在。如果沒有索引,那么SQL Server使用表掃描的方法訪問數據庫中的數據。查詢處理器根據分布的統計信息生成該查詢語句的優化執行規劃,以提高訪問數據的效率為目標,確定是使用表掃描還是使用索引。 索引的選項 在創建索引時,可以指定一些選項,通過使用這些選項,可以優化索引的性能。這些選項包括FILLFACTOR選項、PAD_INDEX選項和SORTED_DATA_REORG選項。 使用FILLFACTOR選項,可以優化插入語句和修改語句的性能。當某個索引頁變滿時,SQL Server必須花費時間分解該頁,以便為新的記錄行騰出空間。使用FILLFACTOR選項,就是在葉級索引頁上分配一定百分比的自由空間,以便減少頁的分解時間。當在有數據的表中創建索引時,可以使用FILLFACTOR選項指定每一個葉級索引節點的填充的百分比。缺省值是0,該數值等價于100。在創建索引的時候,內部索引節點總是留有了一定的空間,這個空間足夠容納一個或者兩個表中的記錄。在沒有數據的表中,當創建索引的時候,不要使用該選項,因為這時該選項是沒有實際意義的。另外,該選項的數值在創建時指定以后,不能動態地得到維護,因此,只應該在有數據的表中創建索引時才使用。 PAD_INDEX 選項將FILLFACTOR選項的數值同樣也用于內部的索引節點,使內部的索引節點的填充度與葉級索引的節點中的填充度相同。如果沒有指定FILLFACTOR選項,那么單獨指定PAD_INDEX選項是沒有實際意義的,這是因為PAD_INDEX選項的取值是由FILLFACTOR選項的取值確定的。 當創建聚簇索引時,SORTED_DATA_REORG選項清除排序,因此可以減少建立聚簇索引所需要的時間。當在一個已經變成碎塊的表上創建或者重建聚簇索引時,使用SORTED_DATA_REORG選項可以壓縮數據頁。當重新需要在索引上應用填充度時,也使用該選項。當使用 SORTED_DATA_REORG選項時,應該考慮這些因素:SQL Server確認每一個關鍵值是否比前一個關鍵值高,如果都不高,那么不能創建索引;SQL Server要求1.2倍的表空間來物理地重新組織數據;使用SORTED_DATA_REORG選項,通過清除排序進程而加快索引創建進程;從表中物理地拷貝數據;當某一個行被刪除時,其所占的空間可以重新利用;創建全部非聚簇索引;如果希望把葉級頁填充到一定的百分比,可以同時使用 FILLFACTOR選項和SORTED_DATA_REORG選項。 索引的維護 為了維護系統性能,索引在創建之后,由于頻繁地對數據進行增加、刪除、修改等操作使得索引頁發生碎塊,因此,必須對索引進行維護。 使用DBCC SHOWCONTIG語句,可以顯示表的數據和索引的碎塊信息。當執行DBCC SHOWCONTIG語句時,SQL Server瀏覽葉級上的整個索引頁,來確定表或者指定的索引是否嚴重碎塊。DBCC SHOWCONTIG語句還能確定數據頁和索引頁是否已經滿了。當對表進行大量的修改或者增加大量的數據之后,或者表的查詢非常慢時,應該在這些表上執行 DBCC SHOWCONTIG語句。當執行DBCC SHOWCONTIG語句時,應該考慮這些因素:當執行DBCC SHOWCONTIG語句時,SQL Server要求指定表的ID號或者索引的ID號,表的ID號或者索引的ID號可以從系統表sysindexes中得到;應該確定多長時間使用一次 DBCC SHOWCONTIG語句,這個時間長度要根據表的活動情況來定,每天、每周或者每月都可以。 使用DBCC DBREINDEX語句重建表的一個或者多個索引。當希望重建索引和當表上有主鍵約束或者唯一性鍵約束時,執行DBCC DBREINDEX語句。除此之外,執行DBCC DBREINDEX語句還可以重新組織葉級索引頁的存儲空間、刪除碎塊和重新計算索引統計。當使用執行DBCC DBREINDEX語句時,應該考慮這些因素:根據指定的填充度,系統重新填充每一個葉級頁;使用DBCC DBREINDEX語句重建主鍵約束或者唯一性鍵約束的索引;使用SORTED_DATA_REORG選項可以更快地創建聚簇索引,如果沒有排列關鍵值,那么不能使用DBCC DBREINDEX語句;DBCC DBREINDEX語句不支持系統表。另外,還可以使用數據庫維護規劃向導自動地進行重建索引的進程。 統計信息是存儲在SQL Server中的列數據的樣本。這些數據一般地用于索引列,但是還可以為非索引列創建統計。SQL Server維護某一個索引關鍵值的分布統計信息,并且使用這些統計信息來確定在查詢進程中哪一個索引是有用的。查詢的優化依賴于這些統計信息的分布準確度。查詢優化器使用這些數據樣本來決定是使用表掃描還是使用索引。當表中數據發生變化時,SQL Server周期性地自動修改統計信息。索引統計被自動地修改,索引中的關鍵值顯著變化。統計信息修改的頻率由索引中的數據量和數據改變量確定。例如,如果表中有10000行數據,1000行數據修改了,那么統計信息可能需要修改。然而,如果只有50行記錄修改了,那么仍然保持當前的統計信息。除了系統自動修改之外,用戶還可以通過執行UPDATE STATISTICS語句或者sp_updatestats系統存儲過程來手工修改統計信息。使用UPDATE STATISTICS語句既可以修改表中的全部索引,也可以修改指定的索引。 使用SHOWPLAN和STATISTICS IO語句可以分析索引和查詢性能。使用這些語句可以更好地調整查詢和索引。SHOWPLAN語句顯示在連接表中使用的查詢優化器的每一步以及表明使用哪一個索引訪問數據。使用SHOWPLAN語句可以查看指定查詢的查詢規劃。當使用SHOWPLAN語句時,應該考慮這些因素。SET SHOWPLAN_ALL語句返回的輸出結果比SET SHOWPLAN_TEXT語句返回的輸出結果詳細。然而,應用程序必須能夠處理SET SHOWPLAN_ALL語句返回的輸出結果。SHOWPLAN語句生成的信息只能針對一個會話。如果重新連接SQL Server,那么必須重新執行SHOWPLAN語句。STATISTICS IO語句表明輸入輸出的數量,這些輸入輸出用來返回結果集和顯示指定查詢的邏輯的和物理的I/O的信息。可以使用這些信息來確定是否應該重寫查詢語句或者重新設計索引。使用STATISTICS IO語句可以查看用來處理指定查詢的I/O信息。 就象SHOWPLAN語句一樣,優化器隱藏也用來調整查詢性能。優化器隱藏可以對查詢性能提供較小的改進,并且如果索引策略發生了改變,那么這種優化器隱藏就毫無用處了。因此,限制使用優化器隱藏,這是因為優化器隱藏更有效率和更有柔性。當使用優化器隱藏時,考慮這些規則:指定索引名稱、當 index_id為0時為使用表掃描、當index_id為1時為使用聚簇索引;優化器隱藏覆蓋查詢優化器,如果數據或者環境發生了變化,那么必須修改優化器隱藏。 ------------------------------------------------------------------------------ mysql建立索引的一些小規則 1、表的主鍵、外鍵必須有索引;2、數據量超過300的表應該有索引;3、經常與其他表進行連接的表,在連接字段上應該建立索引;4、經常出現在Where子句中的字段,特別是大表的字段,應該建立索引;5、索引應該建在選擇性高的字段上;6、索引應該建在小字段上,對于大的文本字段甚至超長字段,不要建索引;7、復合索引的建立需要進行仔細分析;盡量考慮用單字段索引代替:A、正確選擇復合索引中的主列字段,一般是選擇性較好的字段;B、復合索引的幾個字段是否經常同時以AND方式出現在Where子句中?單字段查詢是否極少甚至沒有?如果是,則可以建立復合索引;否則考慮單字段索引;C、如果復合索引中包含的字段經常單獨出現在Where子句中,則分解為多個單字段索引;D、如果復合索引所包含的字段超過3個,那么仔細考慮其必要性,考慮減少復合的字段;E、如果既有單字段索引,又有這幾個字段上的復合索引,一般可以刪除復合索引;8、頻繁進行數據操作的表,不要建立太多的索引;9、刪除無用的索引,避免對執行計劃造成負面影響;以上是一些普遍的建立索引時的判斷依據。一言以蔽之,索引的建立必須慎重,對每個索引的必要性都應該經過仔細分析,要有建立的依據。因為太多的索引與不充分、不正確的索引對性能都毫無益處:在表上建立的每個索引都會增加存儲開銷,索引對于插入、刪除、更新操作也會增加處理上的開銷。另外,過多的復合索引,在有單字段索引的情況下,一般都是沒有存在價值的;相反,還會降低數據增加刪除時的性能,特別是對頻繁更新的表來說,負面影響更大。 ------------------------------------------------------------------------數據表創建規則
寫在前邊: 規范是一種習慣,在Oracle數據庫中筆者認為表中的字段命名規范需要引起注意,當考慮使用SSM作為框架的時候,Mybatis 的逆向工程能夠根據數據庫表名和數據庫名字段名自動生成pojo類,其中pojo類中的屬性名稱就是根據數據庫字段名來進行命名的。 當然筆者建議例如用戶ID 數據庫字段應寫為“USER_ID”。 這樣逆向工程生成的pojo屬性 是“userId“” 符合java的駝峰命名法。數據庫字段命名 Mybatis逆向工程pojo屬性名 USER_ID userId user_name userName 1、編寫目的使用統一的命名和編碼規范,使數據庫命名及編碼風格標準化,以便于閱讀、理解和繼承。2、適用范圍本規范適用于公司范圍內所有以ORACLE作為后臺數據庫的應用系統和項目開發工作。3、對象命名規范 3.1 數據庫和SID數據庫名定義為系統名+模塊名★ 全局數據庫名和例程SID 名要求一致★ 因SID 名只能包含字符和數字,所以全局數據庫名和SID 名中不能含有“_”等字符3.2 表相關 3.2.1 表空間★ 面向用戶的專用數據表空間以用戶名+_+data命名 ,如Aud 用戶專用數據表空間可命名為Aud_data★ 面向用戶的專用索引表空間以用戶名+_+idx命名★ 面向用戶的專用臨時表空間以用戶名+_+tmp命名★ 面向用戶的專用回滾段表空間以用戶名+_+rbs 命名★ 面向應用的表空間以應用名+_data/應用名+_idx/應用名+_tmp/應用名+_rbs 命名★ LOB 段數據專用表空間以其數據表空間+_+lobs 命名,如上例中數據表空間為Aud_data,則LOB 段表空間可命名為Aud_data_lobs3.2.2 表空間文件表空間文件命名以表空間名+兩位數序號(序號從01開始)組成,如Aud_data01 等3.2.3 表表命名要遵循以下原則:★ 一般表采用“系統名+t_+模塊名+_+表義名” 格式構成★ 若數據庫中只含有單個模塊,命名可采用“系統名+t_+表義名”格式構成★ 模塊名或表義名均以其漢語拼音的首字符命名,表義名中漢語拼音均采用小寫,且字符間不加分割符;★ 表別名命名規則:取表義名的前3 個字符加最后一個字符。如果存在沖突,適當增加字符(如取表義名的前4 個字符加最后一個字符等)★ 臨時表采用“系統名+t_tmp_+表義名” 格式構成★ 表的命名如dft_gy_cbap:系統名(電費 df)+t_+模塊名(高壓 gy)++表義名(抄表安排 cbap) dft_cbbj: 系統名(電費 df)+t+表義名(抄表標記 cbbj) dft_tmp_hj: 系統名(電費 df)+tmp+表義名(合計hj)(此處為臨時表) ★ 關聯表命名為Re_表A_表B,Re 是Relative的縮寫,表A 和表B均采用其表義名或縮寫形式。3.2.4 屬性(列或字段)屬性命名遵循以下原則:★ 采用有意義的列名,為實際含義的漢語拼音的首字符,且字符間不加任何分割符★ 屬性名前不要加表名等作為前綴★ 屬性后不加任何類型標識作為后綴★ 不要使用“ID”作為列名★ 關聯字段命名以 “cd++關聯表的表義名(或縮寫)++字段名”進行3.2.5 主鍵★ 任何表都必須定義主鍵★ 表主鍵命名為:“pk++表名(或縮寫)++主鍵標識”如“pk_YHXX_IDKH”等3.2.6 外鍵表外鍵命名為: “fk++表名(或縮寫)+主表名(或縮寫)+_+主鍵標識”如“fk_YHLX_YHXX_SFZH”等3.2.7 CHECK約束CHECK 約束命名為: “chk+_+CHECK約束的列名(或縮寫)”3.2.8 UNIQUE約束UNIQUE 約束命名為: “unq+_+UNIQUE約束的列名(或縮寫)”3.2.9 索引索引的命名為:“表名(或縮寫)+_+列名+_idx”。其中多單詞組成的屬性列列名取前幾個單詞首字符再加末單詞首字符組成如yd_kh 表khid 上的index: yd_kh_khid_idx3.2.10 觸發器★ AFTER型觸發器系統名+tr_+<表名>_+ +[_row]★ BEFORE型觸發器系統名+tr_+<表名>+bef +[_row]★ INSTEAD OF型觸發器系統名+ti_+<表名>+_+ +[_row]★ 各種類型的觸發器中i,u,d 分別表示insert、update 和delete行級觸發器,后加_row 標識,語句級觸發器不加,如 yddftr_CSH_i_row3.2.11 簇簇以簇中要存儲的各個表(或表別名)及表間加and的組成 命名,即表“A+And+表B…”,如存儲GR(工人)和GRJN(工人技能)表的簇命名為GRAndGRJN3.3 視圖視圖命名以系統名v_+模塊名作為前綴,其他命名規則和表的命名類似3.4 序列序列命名以seq_+含義名組成3.5 同義詞同義詞命名與其基礎對象的名稱一致,但要去除其用戶前綴或含有遠程數據庫鏈接的后綴3.6 存儲對象相關 3.6.1 存儲過程存儲過程命名由“系統名+sp+_+存儲過程標識(縮寫)”組成存儲過程標識要以實際含義的漢語拼音的首字符構成,并用下劃線分割各個組成部分。如增加代理商的帳戶的存儲過程為“sfsp_ZJDLSZH”。3.6.2 函數函數命名由“系統名+f+_+函數標識”組成3.6.3 包包命名由“系統名+pkg+_+包標識”組成3.6.4 函數文本中的變量采用下列格式命名:★ 參數變量命名采用“i (o或io)+_+名稱”形式,前綴i 或o 表輸入還是輸出參數★ 過程變量命名采用“l+_+名稱”形式★ 全局包變量命名采用“g+_+名稱”形式★ 游標變量命名采用“名稱+_+cur”形式★ 常量型變量命名采用“c+_+名稱”形式★ 變量名采用小寫,若屬于詞組形式,用下劃線分隔每個單詞★ 變量用來存放表中的列或行數據值時,使用%TYPE、%ROWTYPE 方式聲明變量,使變量聲明的類型與表中的保持同步,隨表的變化而變化3.7 用戶及角色★ 用戶命名由“系統名稱++user++名詞(或縮寫)或名詞短語(或縮寫)”組成★ 角色命名由“系統名稱++role++名詞(或縮寫)或名詞短語(或縮寫)”組成3.8 數據庫鏈接★ 數據庫鏈接命名由“遠程服務器名++數據庫名++link”組成★ 若遠程服務器名和數據庫名一致,上式“_+數據庫名”部分省去3.9 命名中的其它注意事項★ 命名都不得超過30個字符。★ 不要在對象名的字符之間留空格★ 小心保留詞,要保證你的命名沒有和保留詞、數據庫系統或者常用訪問方法沖突 4、 編碼規范4.1 一般性注釋 4.1.1 注釋盡可能簡潔、詳細而全面4.1.2 創建每一數據庫對象時都要加上COMMENT ON注釋,以說明該對象的功能和用途;建表時,對某些數據列也要加上COMMENT ON注釋,以說明該列和/或列取值的含義。如:XX 表中有CZZT列屬性為NUMBER(10, 0)可加COMMENT ON 注釋如下COMMENT ON COLUMN XX.CZZT IS ‘0 = 正常, 1 = 等待, 2 = 超時, 3 = 登出’4.1.3 注釋語法包含兩種情況:單行注釋、多行注釋單行注釋:注釋前有兩個連字符(–),一般對變量、條件子句可以采用該類注釋。多行注釋:符號/和/之間的內容為注釋內容。對某項完整的操作建議使用該類注釋。4.2 函數文本注釋 4.2.1 在每一個塊和過程(存儲過程、函數、包、觸發器、視圖等)的開頭放置注釋 /*************************************** ************* name : –函數名 *function : –函數功能 *input : –輸入參數 *output : –輸出參數 *author : –作者 *CreateDate : –創建時間 *UpdateDate : –函數更改信息(包括作者、時間、更改內容等) ***************************************** *************/ CREATE [OR REPLACE] PROCEDURE dfsp_xxx … 4.2.2 傳入參數的含義應該有所說明。如果取值范圍確定,也應該一并說明。取值有特定含義的變量(如boolean類型變量),應給出每個值的含義。4.2.3 在每一個變量聲明的旁邊添加注釋。說明該變量要用作什么通常,簡單使用單行注釋就行了,例如l_sfzh CHAR(11) –身份證號碼4.2.4 在塊的每個主要部分之前添加注釋在塊的每個主要部分之前增加注釋,解釋下—組語句目的,最好是說明該段語句及算法的目的以及要得到的結果,但不要對其細節進行過多的描述4.2.5 在塊和過程的開頭注釋中還可以增加要訪問的數據庫等信息 4.3 常用SQL 語句的編寫規范4.3.1 CREATE語句 4.3.2 SELECT語句 查詢語句采用以下原則編寫(可最大化重用共享池中的SQL 語句,提高應用程序性能):★ 將SELECT 語句分為5部分:(1) 由SELECT 開頭,后跟一個顯示查詢結果的列表;(2) 由FROM 開頭,后跟一個或多個獲取數據所涉及的表;(3) 由WHERE 開頭,后跟一個或多個確定所需值的條件;(4) 由GROUP BY開頭,后跟一個或多個表列名,通過這些列以對查詢結果進行匯總;(5) 由ORDER BY開頭,后跟一個或多個表列名,通過這些列以對查詢結果進行排序。★ 每個部分分行編寫,將每一行的第一個關鍵字與第一行的SELECT尾部對齊,如 ★ 關鍵字用大寫,列名和表名采用小寫★ 語句中嵌入逗號時,在逗號后面加一空格,當逗號是最后一個字符時,把它放在本行★ 當語句的同一部分要延續到下一行時,按下列格式排列: ★ 將語句中WHERE 和AND 部分格式化,書寫布局類似于 ★ 當語句中出現括號時,括號的兩邊不留空格★ 在SQL 語句使用運算符時,操作兩邊應各留一個空格,如 4.3.3 INSERT語句 4.3.4 UPDATE語句 4.3.5 DELETE語句 4.4 條件執行語句(IF)編寫規范條件執行語句IF…ELSE 按以下格式編寫 (1) 在IF…THEN和ELSE(或ELSIF)及ELSE…THEN和END IF間可包含一條或多條PL/SQL語句,而不需要加BEGIN 和END(2) IF…ELSE…ENDIF 語句可以嵌套(3) 注意ELSIF的寫法4.5 循環語句編寫規范 4.5.1 簡單循環語句 4.5.2 FOR循環語句FOR 變量 IN [變量取值范圍] 4.5.3 WHILE循環語句WHILE <條件表達式> 4.6 函數文本(存儲過程、函數和包等)★ 對于存儲過程、函數等程序塊都要有異常處理部分,在異常部分的最后都要設置OTHERS異常情態處理器,以提高程序的自檢能力,格式如下: ★ 對于子程序、觸發器、包等帶名的程序塊,要使用結束標識,如 CREATE OR REPLACE PROCEDURE XXXsp_XXX IS … BEGIN … END XXXsp_XXX;/* 此處的過程名XXXsp_XXX是可選的,規范要求寫上,與塊開始的CREATE相對應 */ ------------------------------------------------------------------------備用字段 / 保留字段 / 預留字段
數據庫設計誤區:備用字段 / 保留字段 / 預留字段【現象描述】 在數據表中,不僅設計了當前所需要的字段,而且還在其中留出幾個字段作為備用。 比方說,我設計了一個人員表(Person),其中已經添加了各種必要的字段,包括姓名(Name)、性別(Sex)、出生年月日(birthday)等等。大功告成之后,我忽然想到,將來系統中應該還會有很多其它與人相關的內容吧,比方說畢業院校,比方說工作單位等等,盡管現在根本不需要填寫,以后可能還是會用到的吧。拍腦袋一項,那就加入5個varchar2型的字段,分別叫做Text1、Text2……Text5,然后又想,應該還有一些日期型的字段需要備用,就又建立了三個date型的字段,分別起名叫做date1、date2、date3,……【原因分析】 大家應該已經看出問題了,在這個數據表中存在大量暫時無用的字段,我們可以稱之為備用字段,它們的作用是什么呢?就是以防萬一,防備可能的情況。 這似乎可以叫做防患于未然,等到需要的時候,就不需在表中增加新的字段了,而且這樣做的話,一個表的數據應該會被存儲在相鄰的物理空間中,這對于性能也是有好處的。 另外的原因就是,在古老的數據庫中,如果改變數據庫的定義(包括增加字段、改變字段的類型、刪除字段等等),那么其中所有的數據就會丟失,所以這項工作非常麻煩,我們需要先建立臨時表,將數據備份出來,然后創建新表,將數據導入其中,最后再刪除原來的表。【問題所在】 這樣的做法對于項目會導致很多問題,而且原先想要解決的問題并不一定能夠解決,不信的話,請往下看。 問題一:增加大量備用字段,必定會浪費很多空間,盡管其中可能都沒有具體的數據,但是僅僅是空字段也會占據一定的空間的。 問題二:由于命名的特點,如果沒有完善的文檔管理流程,用不了多久(可能也就是兩三年),就沒有人能夠說清楚到底哪個字段代表的是什么意義了。就算有文檔管理,這些管理工作也會比較麻煩,而且在每次使用的時候都需要申請,還有可能會出現沖突的情況。 問題三:增加了這些備用字段就真的會夠用嗎?不一定,因為我們只是每個類型的字段留出幾個備用,如果數量超過,或者要使用特殊的、不常用的類型的時候,還是需要增加新的字段。比方說在上述的Person表中,我們要存儲照片,那么可能就要增加一個blob類型的photo字段,這在初期設計的時候可不一定會留出這樣的備用字段。而且如果沒有完善的管理,誰又能說清楚倒底哪個字段已經被使用,哪個字段還可以使用呢?到時候還不是要增加新的字段。【解決方案】 其實上面的這種設計方式就是一種“過度設計”,我們應該做的就是“按需設計”,在經過詳細有效的分析之后,在數據表中只放置必要的字段,而不要留出大量的備用字段。 當需要增加相關的信息的時候,就要具體情況具體分析: 1. 如果數量很少,而且信息的性質與原表密切相關,那么就可以直接在原表上增加字段,并將相關的數據更新進去; 2. 如果數量較大,或者并非是原表對象至關重要的屬性,那么就可以新增一個表,然后通過鍵值連接起來; 3. 對于表的數據的存儲位置所導致的性能問題,我們可以通過在特定時間對數據庫的數據進行重組來解決,而這項工作對于長期運行的數據庫來說,也是需要定期進行的。 --------------------- 項目設計數據庫表時是否需要在表中加備用預留字段?背景:以前做項目,有用過SSH框架,或者SSM框架,數據庫有Oracle,DB2。在開發過程中,有時因數據庫設計者未考慮周到,業務實體有一個屬性沒有對應的字段,因此需要在數據庫表加一個字段,又由于此字段要求不可為空,并且在開發階段,測試數據不多,有時是drop掉了原來的表,增加了一個字段再重新建了一張表。有時一些表,設計表時會在后面加幾個類型為varchar的預留字段。最近和朋友聊到這個問題,就是:為什么要這么做,好處是什么,怎么權衡這個問題。在遇到這個問題之后引起我思考:預留字段這個通用的做法是否能減少開發階段由于考慮不周到,或后續維護階段因為需求變更或者擴展改造而需要增加字段而造成的麻煩?就此與一些朋友進行了討論,根據以往的項目經驗和設計原則給出了一些解答,以及怎樣的設計能確保數據庫健壯,可擴展。大家意見不一,以下是正反方的一些意見和看法。———————————————正反觀點:需要 原因: 1. 持久層的設計,數據庫表結構不應輕易變更。因此應設置備用字段。啟用備用字段后,只修改代碼,在代碼中增加注釋和并文檔說明即可,不需要改動數據庫結構,更方便。 2. 如果沒有備用字段,如果后期要加字段的話,用add column的方法會改變原先的數據庫存儲結構,造成數據移動,移動需要時間,而且會移動到其他數據塊,add column會影響數據庫性能。 3. 對于反方提到的規范問題,只要代碼和文檔規范是可以避免這樣的問題的,即使遇到這樣的問題,也比修改表名帶來的危險要小,除了要修改代碼、存儲過程、配置文件中的表名,還要考慮數據的遷移等問題,如此多的改動難免會出現這樣那樣的問題,因此保證系統的穩定性來看,攜帶幾個擴展字段為了后續使用也無妨。———————————————反方觀點:不需要1. 如果要預留字段的話,第一個需要全面考慮的問題,如何評估:a. 預留多少個字段;b. 預留什么類型的;c. 預留的字段不適用怎么辦——比如長度/精度不夠;d. 預留的字段允許不允許空值呢; 2. 數據庫設置備用字段無法在字段名上體現其意義,不規范,后期維護麻煩。在需要增加字段的時候如果直接add column,也不會有太大工作,但能保證數據庫字段的規范。雖然在啟用備用字段的時候可以文檔說明,但在POJO上對應其屬性為attribute1,attribute2等,代碼的可讀性不強。而且,預留字段全部統一為varchar,也不太合適。 3. 預留字段畢竟是數據庫表字段,會占用數據庫存儲空間。4. 添加字段出現的性能問題,我之前的項目中一般都是定期對數據庫進行數據整理、重組操作。各方案都有不同的側重點,最終的你會選擇選擇哪種方案呢?——————————————————————————————CSDN有另一篇博文,地址是:http://blog.csdn.net/iw1210/article/details/44752771,分析也很不錯,給出了相應的解決方案,詳細內容如下:數據庫設計誤區:備用字段 / 保留字段 / 預留字段【現象描述】 在數據表中,不僅設計了當前所需要的字段,而且還在其中留出幾個字段作為備用。 比方說,我設計了一個人員表(Person),其中已經添加了各種必要的字段,包括姓名(Name)、性別(Sex)、出生年月日(birthday)等等。大功告成之后,我忽然想到,將來系統中應該還會有很多其它與人相關的內容吧,比方說畢業院校,比方說工作單位等等,盡管現在根本不需要填寫,以后可能還是會用到的吧。拍腦袋一項,那就加入5個varchar2型的字段,分別叫做Text1、Text2……Text5,然后又想,應該還有一些日期型的字段需要備用,就又建立了三個date型的字段,分別起名叫做date1、date2、date3,……【原因分析】 大家應該已經看出問題了,在這個數據表中存在大量暫時無用的字段,我們可以稱之為備用字段,它們的作用是什么呢?就是以防萬一,防備可能的情況。 這似乎可以叫做防患于未然,等到需要的時候,就不需在表中增加新的字段了,而且這樣做的話,一個表的數據應該會被存儲在相鄰的物理空間中,這對于性能也是有好處的。 另外的原因就是,在古老的數據庫中,如果改變數據庫的定義(包括增加字段、改變字段的類型、刪除字段等等),那么其中所有的數據就會丟失,所以這項工作非常麻煩,我們需要先建立臨時表,將數據備份出來,然后創建新表,將數據導入其中,最后再刪除原來的表。【問題所在】 這樣的做法對于項目會導致很多問題,而且原先想要解決的問題并不一定能夠解決,不信的話,請往下看。 問題一:增加大量備用字段,必定會浪費很多空間,盡管其中可能都沒有具體的數據,但是僅僅是空字段也會占據一定的空間的。 問題二:由于命名的特點,如果沒有完善的文檔管理流程,用不了多久(可能也就是兩三年),就沒有人能夠說清楚到底哪個字段代表的是什么意義了。就算有文檔管理,這些管理工作也會比較麻煩,而且在每次使用的時候都需要申請,還有可能會出現沖突的情況。 問題三:增加了這些備用字段就真的會夠用嗎?不一定,因為我們只是每個類型的字段留出幾個備用,如果數量超過,或者要使用特殊的、不常用的類型的時候,還是需要增加新的字段。比方說在上述的Person表中,我們要存儲照片,那么可能就要增加一個blob類型的photo字段,這在初期設計的時候可不一定會留出這樣的備用字段。而且如果沒有完善的管理,誰又能說清楚倒底哪個字段已經被使用,哪個字段還可以使用呢?到時候還不是要增加新的字段。【解決方案】 其實上面的這種設計方式就是一種“過度設計”,我們應該做的就是“按需設計”,在經過詳細有效的分析之后,在數據表中只放置必要的字段,而不要留出大量的備用字段。 當需要增加相關的信息的時候,就要具體情況具體分析: 1. 如果數量很少,而且信息的性質與原表密切相關,那么就可以直接在原表上增加字段,并將相關的數據更新進去; 2. 如果數量較大,或者并非是原表對象至關重要的屬性,那么就可以新增一個表,然后通過鍵值連接起來; 3. 對于表的數據的存儲位置所導致的性能問題,我們可以通過在特定時間對數據庫的數據進行重組來解決,而這項工作對于長期運行的數據庫來說,也是需要定期進行的。---------------------?
總結
以上是生活随笔為你收集整理的数据库建立索引、数据表创建规则、备用字段 / 保留字段 / 预留字段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库表设计、 数据库分层、myslq水
- 下一篇: linux cmake编译源码,linu