1、開發數據庫時常用命名規范
1>、使用不包含數字的單數表名,如果必要的話可以增加模塊名前綴。
2>、對於主鍵的命名,使用表名+ID的形式。
3>、作為外鍵的列的名字應該與它們所對應的主鍵的列名相同,除非該外鍵維護的是一種自反/遞歸的關系。
4>、避免使用縮寫。
2、主鍵設計原則
1>、主鍵用途:惟一標識一行;作為一個可以被外部鍵有效引用的對象。
2>、主鍵應當對用戶沒有意義。
3>、主鍵應該是單列的,以便提高連接和篩選操作的效率。復合主鍵僅用於描述多對多關系的連接表中用兩個外鍵來作為主鍵。
4>、永遠不要更新主鍵。
5>、主鍵不應包含動態變化的數據,如時間戳、創建時間列、修改時間列等。
6>、主鍵應當由計算機自動生成。
7>、主鍵是通過Unique約束(非空約束)以及聚集或非聚集惟一索引來實現的。主鍵應當是沒有實際意義的、單列的、由計算機生成的、不可編輯的,而且對用戶來說是不可見的。
2.1、創建主鍵
在表結構設計中使用聚集索引創建索引,並不是最好,由於每個表只能創建一個聚集索引,這樣的做法會失去為每個表創建其他更有效的聚集索引的機會。
sql語句創建非聚集索引主鍵:
CREATE TABLE dbo.Product ( ProductID INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, ProductName VARCHAR(100) NULL )
2.2、主鍵使用標識列
標識列優點:易於人工識別,占用空間小而且快。
將標識列設置為使用聚集索引的主鍵(這是一種很常見,但並不好的方法),當單個用戶檢索一行記錄的時候,其速度極快。然而,這樣的設計方法會在數據庫中形成鎖爭用的熱點。
2.3、主鍵使用GUID
GUID是由16個字節的16進制數組成,不會出現重復的數字。與標識列相比,GUID可以在更大的范圍保證惟一性。
GUID優點:復制使用GUID主鍵的數據庫時不必額外做全面的檢查,GUID值的隨機性可以減少數據庫的熱點,可以使用多種方法來生成GUID的值。
sql語句創建GUID主鍵表:
CREATE TABLE dbo.Product ( ProductID UNIQUEIDENTIFIER DEFAULT(NEWID()) PRIMARY KEY NONCLUSTERED, ProductName VARCHAR(100) NULL )
3、外鍵設計原則
外鍵可以引用除了臨時表以外的其他表的主鍵、Unique約束或惟一索引的列。
4、索引
SQL Server使用兩種基本類型的索引:聚集索引和非聚集索引。一般創建索引的列為:主鍵、外鍵、order by列。
索引設計原則:
◊
索引並不是越多越好,一個表中如果有大量的索引,不僅占用大量的磁盤空間,而且會影響INSERT、DELETE、UPDATE等語句的性能。當表數據更新時,索引也會進行調整和更新。
◊ 避免對經常更新的表進行過多的索引,並且索引的列盡可能少。對經常用於查詢的字段應該創建索引,但要避免添加不必要的字段。
◊ 數據量小的表最好不要使用索引,由於數據較少,查詢花費的時間可能比遍歷索引的時間還要短,索引可能不會產生優化效果。
◊
在條件表達式中經常用到的、不同值較多的列上建立索引,在不同值少的列上不要建立索引。比如【性別】字段是只有【男】和【女】兩個不同值,因此就無須建立索引。如果建立索引,不但不會提高效率,反而會嚴重降低更新速度。
◊ 當唯一性是某種數據本身的特征時,指定唯一索引。使用唯一索引能夠確保定義的列的數據完整性,提高查詢速度。
◊ 在頻繁進行排序或分組(ORDER BY或GROUP BY)的列上建立索引,如果待排序的列有多個,可以在這些列上建立組合索引。
4.1、非聚集索引
創建非聚集索引SQL語句:
CREATE NONCLUSTERED INDEX IX_ProductNo ON dbo.Product(ProductNo)
4.2、聚集索引
聚集索引將表中的記錄行與索引鍵值以同樣的物理順序存儲。由於數據只可能有一種物理存儲順序,因此每個表只能有一個聚集索引。通過聚集索引檢索數據只需要更少的邏輯讀取的次數,任意非聚集索引都將指向聚集索引的ID而不需要指向數據頁。
聚集索引將具有同樣索引鍵值的記錄行集中到盡可能少的數據頁中,因而減少了檢索一組記錄時需要讀取的數據頁數。所以,對於那些經常作為條件來查詢一組記錄的列,如類似於OrderDetail.OrderID這樣的從表外鍵,對其建立聚集索引是一個很好的選擇。基於同樣的原因,對於只返回一行記錄的查詢,使用聚集索引不會明顯地提高性能。
對於聚集索引,常見的錯誤認識有:
1>、聚集索引會降低insert操作的速度,因為必須要向后移動一半的數據來為插入的行騰出空間。這種認識是錯誤的,因為可以利用填充因子控制填充的百分比,從而在索引頁上為新插入的數據保留空間。如果索引頁填滿了,SQL
Server將會進行頁拆分,在這種情況下只有第一個頁才會受到影響。
2>、在使用標識列的主鍵上創建聚集索引是一種好的設計方法,它可以使對表的操作達到最快速度。這種認識是錯誤的,它浪費了創建其他更有效的聚集索引的機會。並且,使用這種方法把每個新插入的記錄行都存儲到表尾部的同一個數據頁中,這將導致數據庫的熱點與鎖爭用。雖然行鎖可以部分地緩解這個熱點問題,但是,根據要鎖定的行的數量、頁上的行的數量、用戶的數量,鎖管理器有可能會把行鎖升級為頁鎖,此時又會出現熱點問題。
3>、聚集索引是具有魔力的。如果哪個查詢的速度不夠快,那么久在該列上創建聚集索引,對於表的操作速度一定會得到提高。這種認識是錯誤的,聚集索引只是比非聚集索引稍微快一點點。因為在每個表上只能創建一個聚集索引,索引它也是一種寶貴的性能資源,只有在那些經常作為條件查詢一組記錄行的列上才應該創建聚集索引。
SQL語句創建聚集索引:
CREATE CLUSTERED INDEX IX_OrderID ON dbo.OrderDetail(OrderID)
SQL語句刪除索引:
DROP INDEX OrderDetail.IX_OrderID
4.3、組合索引
組合索引是擁有多個索引列的聚集或非聚集索引。因為組合索引包含多個索引列,所以只有在創建表之后,才能使用create index
DDL命令來創建。
SQL語句創建組合索引:
CREATE NONCLUSTERED INDEX IX_ProductNoProductName ON dbo.Product(ProductNo,ProductName)
在組合索引中,索引排列的先后順序非常重要。因為只有這樣的一些查詢才能夠使用組合索引:它們在查詢條件中所包含的索引列在組合索引中是從第一個索引列開始按照從左到右的順序依次排列的。上例的組合索引中,索引列的順序是ProductNo、ProductName,只以ProductName為條件的查詢將不會使用這個索引,只有以ProductNo或者ProductNo和ProductName為條件的查詢才能使用這個索引。
4.4、索引選項
1>、Unique索引
SQL Server的索引具有幾個選項,包括惟一性、空間分配和性能選項。
unique索引選項並非只是一個具有惟一約束的索引;對於unique索引可以進行索引優化。在創建主鍵或者unique約束時,系統都會自動地為它們創建unique索引。
CREATE
UNIQUE
INDEX
IX_OrderNo
ON
dbo.
Order
.OrderNo
|
2>、索引填充因子(FillFactor)和填充索引(PAD_INDEX)
索引需要在其索引樹上保留一點空間,這樣,在插入新的記錄時就不必對索引進行重構。填充因子指定了在索引上填有數據空間所占的百分比。
填充因子應該設置為多少才最合適,取決於數據庫的用途。如果數據庫主要用於數據檢索,就應該將填充因子設為較大的值以盡可能填滿一個索引頁的空間。如果需要對表進行大量插入操作,在索引頁上保留一些空間就可以提供更新操作的性能。如果對於表插入操作的數量變化幅度較大,將填充因子設置為一個中間的值,並選擇填充索引選項就比較合適。
CREATE UNIQUE INDEX IX_OrderNo ON dbo.Order.OrderNo WITH FILLFACTOR=85 PAD_INDEX
3>、索引排序選項(ASC|DESC)
盡管SQL Server可以創建降序索引,但不建議改變默認的升序索引順序。這樣做並不能改善性能,但卻容易在今后造成一些混亂。除非明確地在Order
by字句中使用desc選項,否則,所有使用order by字句的查詢仍將按照升序排序。
創建升序或者降序索引的方法是:在create index DDL命令中的列名之后使用asc或者desc選項。
CREATE UNIQUE INDEX IX_OrderNo ON dbo.Order.OrderNo DESC WITH FILLFACTOR=85 PAD_INDEX
4>、忽略重復鍵選項(IGNORE_DUP_KEY)
忽略重復鍵選項不是作用於索引的,它指定了索引對今后的數據修改操作的處理方式。
通常,事務都是原子的,這意味着整個事務中的操作作為一個邏輯單元要么全部成功,要么全部失敗。如果設置了忽略重復鍵選項,允許insert事務只提交那些為unique索引所接收的記錄行,而忽略那些違反了unique索引的惟一性的記錄行。
這樣選項不會破壞unique索引。在表中仍然不會插入重復的值,所以數據庫的一致性是完整無損的,但事務的原子性卻被違反了。
利用這個選項可以方便地向數據庫中導入大量可能存在問題的記錄行,但是消弱了數據庫的ACID屬性。
CREATE UNIQUE INDEX IX_OrderNo ON dbo.Order.OrderNo WITH IGNORE_DUP_KEY