1. 程式人生 > >資料庫建立索引、資料表建立規則、備用欄位 / 保留欄位 / 預留欄位

資料庫建立索引、資料表建立規則、備用欄位 / 保留欄位 / 預留欄位

資料庫建立索引

資料庫、資料表建立索引的原則
資料庫建立索引的原則 
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;

  比如:OOOOOOFFFBBBBBBRRR

  OOOOOO:data object number, 對應dba_objects.data_object_id

  FFF: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/O

  4、 與所索引的表是相互獨立的物理結構

  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 indextable

  as select rownum id,owner,object_name,subobject_name,

  object_id,data_object_id,object_type,created

  from t;

  3. set autotrace trace explain

  4. set timing on

  5. 分析表,可以得到cost

  6. 查詢 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操作,因為要相應的跟新所有的bitmap

  2、 結構:點陣圖索引使用點陣圖作為鍵值,對於表中的每一資料行點陣圖包含了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 job

  Britten Park, Rose Bed 1, Prune

  Britten Park, Rose Bed 1, Mulch

  Britten Park, Rose Bed 1,Spray

  Britten Park, Shrub Bed 1, Mulch

  Britten Park, Shrub Bed 1, Weed

  Britten Park, Shrub Bed 1, Hoe

  ……

  查詢時,以上3列均在where條件中同時出現,所以建立基於以上3列的組合索引。但是發現重複值很多,所以考慮壓縮特性。

  Create index zip_idx

  on landscp(site, feature, job)

  compress 2;

  將索引項分成字首(prefix)和字尾(postfix)兩部分。前兩項被放置到字首部分。

  Prefix 0: Britten Park, Rose Bed 1

  Prefix 1: Britten Park, Shrub Bed 1

  實際所以的結構為:

  0 Prune

  0 Mulch

  0 Spray

  1 Mulch

  1 Weed

  1 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_lobs

3.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_idx

3.2.10 觸發器
  ★ AFTER型觸發器

  系統名+tr_+<表名>_+ +[_row]

  ★ BEFORE型觸發器

  系統名+tr_+<表名>+bef +[_row]

  ★ INSTEAD OF型觸發器

  系統名+ti_+<表名>+_+ +[_row]

  ★ 各種型別的觸發器中

  i,u,d 分別表示insert、update 和delete行級觸發器,後加_row 標識,語句級觸發器不加,如 yddftr_CSH_i_row

3.2.11 簇
  簇以簇中要儲存的各個表(或表別名)及表間加and的組成 命名,即表“A+And+表B…”,如儲存GR(工人)和GRJN(工人技能)表的簇命名為GRAndGRJN

3.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欄位,這在初期設計的時候可不一定會留出這樣的備用欄位。而且如果沒有完善的管理,誰又能說清楚倒底哪個欄位已經被使用,哪個欄位還可以使用