關於Sql Server的一些知識點的定義總結
資料庫完整性:是指資料庫中資料在邏輯上的一致性、正確性、有效性和相容性
實體完整性(Entity Integrity 行完整性):實體完整性指表中行的完整性。主要用於保證操作的資料(記錄)非空、唯一且不重複。即實體完整性要求每個關係(表)有且僅有一個主鍵,每一個主鍵值必須唯一,而且不允許為“空”(NULL)或重複。
域完整性(Domain Integrity 列完整性):是指資料庫表中的列必須滿足某種特定的資料型別或約束。其中約束又包括取值範圍、精度等規定。表中的CHECK、FOREIGN KEY 約束和DEFAULT、 NOT NULL定義都屬於域完整性的範疇。
參照完整性(Referential Integrity)屬於表間規則
參照完整性規則(Referential Integrity)要求:若屬性組F是關係模式R1的主鍵,同時F也是關係模式R2的外來鍵,則在R2的關係中,F的取值只允許兩種可能:空值或等於R1關係中某個主鍵值。
Sql Server的儲存結構,頁、區、堆
頁:用於資料儲存的連續的磁碟空間塊,SQL Server中資料儲存的基本單位是頁,磁碟I/O操作在頁級執行,頁的大小為8KB。每頁的開頭是96位元組的頁頭,用於儲存有關頁的系統資訊,包括頁碼、頁型別、頁的可用空間以及擁有該頁的物件的分配單元ID;其他便是儲存資料的資料行與剩下可用空間,結構圖如下(個人繪製)
區間:區是管理空間的基本單位,一個區是8個物理上連續的頁(即64KB)的集合,所有頁都儲存在區中。SQL Server有兩種型別的區:統一區和混合區。
堆:堆是指不含聚集索引的表,它的資料不按任何順序進行儲存。
聯絡一個堆中的資料的唯一結構是被稱為索引分配對映(IAM)的一個位圖頁,當掃描物件時,SQl server使用IAM頁來遍歷該物件的資料。
堆表內的資料頁和行沒有任何特定的順序,也不連結在一起。資料頁之間唯一的邏輯連線是記錄在 IAM 頁內的資訊
假設某訂單明細表中有100萬條資料,需要查詢某個訂單的明細資料,如下:
select * from T_EPZ_INOUT_ENTRY_DETAIL where entry_apply_id='31227000034000090169'
如果在堆表中進行查詢,SQL Server通過掃描 IAM 頁對堆表進行全表掃描,對entry_apply_id比較100萬次,如果以entry_apply_id欄位建立索引,則因為索引鍵值資料都必定以B-Tree有順序的擺放,所以可採用二分查詢找資料。也就是2的N次方大於記錄數,就可以找到該條資料。而2的20次方大於100萬,因此最多找尋20次就可以找到該條記錄。20次與100萬次的比較,你可以輕鬆感受出效能的差異。
由此引出索引的概念
索引分為聚集索引與非聚集索引
聚集索引 :聚集索引是指資料庫錶行中資料的物理順序與鍵值的邏輯(索引)順序相同。一個表只能有一個聚集索引,因為一個表的物理順序只有一種情況,所以,對應的聚集索引只能有一個。如果某索引不是聚集索引,則表中的行物理順序與索引順序不匹配,與非聚集索引相比,聚集索引有著更快的檢索速度
非聚集索引:非聚集索引是一種索引,該索引中索引的邏輯順序與磁碟上行的物理儲存順序不同
聚集索引與非聚集索引的形象比喻
漢語字典的正文字身就是一個聚集索引。 比如,我們要查“安”字,就會很自然地翻開字典的前幾頁,因為“安”的拼音是“an”,而按照拼音排序漢字的字典是以英文字母“a”開頭並以“z”結尾的,那麼“安”字就自然地排在字典的前部。如果您翻完了所有以“a”開頭的部分仍然找不到這個字,那麼就說明您的字典中沒有這個字;同樣的,如果查“張”字,那您也會將您的字典翻到最後部分,因為“張”的拼音是“zhang”。也就是說,字典的正文部分本身就是一個目錄,您不需要再去查其他目錄來找到您需要找的內容。正文內容本身就是一種按照一定規則排列的目錄稱為“聚集索引”。 每個表只能有一個聚集索引,因為目錄只能按照一種方法進行排序 如果您認識某個字,您可以快速地從自動中查到這個字。但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛才的方法找到您要查的字,而需要去根據“偏旁部首”查到您要找的字,然後根據這個字後的頁碼直接翻到某頁來找到您要找的字。但您結合“部首目錄”和“檢字表”而查到的字的排序並不是真正的正文的排序方法,比如您查“張”字,我們可以看到在查部首之後的檢字表中“張”的頁碼是672頁,檢字表中“張”的上面是“馳”字,但頁碼卻是63頁,“張”的下面是“弩”字,頁面是390頁。很顯然,這些字並不是真正的分別位於“張”字的上下方,現在您看到的連續的“馳、張、弩”三字實際上就是他們在非聚集索引中的排序,是字典正文中的字在非聚集索引中的對映。我們可以通過這種方式來找到您所需要的字,但它需要兩個過程,先找到目錄中的結果,然後再翻到您所需要的頁碼。我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱為“非聚集索引”。 如圖,表中存放的資料是雜亂無章的,沒有按照姓名進行排序。我們將資料的姓名提取出來按照姓名建立一個非聚集索引。索引中姓名是排好序的,且索引所佔用的空間遠遠小於表中資料所佔用的空間,當我們查詢表中某條資料時候,將不再進行全表掃描,而對索引進行掃描,得到想要的資料再定位到表中具體的資料。 但是 在非聚集索引上,要掃描某個具體的姓名也得耗費一定的時間,進一步優化,在其上面在加一個Non-leaf level (非葉節點)可以 B樹演算法快速的定位。極大的提高了查詢速度 聚集索引的查詢就是按B樹查詢 如何查詢表中的索引? inidex_id = 0 說明表中無索引 inidex_id = 1 表中為聚集索引, inidex_id = 2或者3.。。。。為非聚集索引。 運用索引遇到的問題以及技術 頁分裂、填充因子、碎片整理、索引統計 頁分裂:因為在非聚集索引中或者有序的資料中 如 在a b e f中要插入新的資料 c ,那麼c在物理順序中將放入f的後面,成為 a b e f c這樣變造成了頁分裂。 可以用索引整理、或者在建表時定義填充因子(就是頁建立之初,讓每個頁儲存的資料佔頁的比列)解決頁分裂的情況
dbcc showcontig(Tstudent,non_sname) --Tstudent表明,PK_TStudent索引名 ,查詢頁分裂情況 dbcc indexdefrag(schoolDB,Tstudent,non_sname)--索引整理 create nonclustered index non_sname on TStudent(sname) with drop_existing,fillfactor = 50--重建索引,並且制定填充因子 dbcc show_statistics(tstudent,non_sname)--檢視索引統計 update statistics schooldb.dbo.tstudent --人工更新表中所有索引的統計 update statistics schooldb.dbo.tstudent non_sname --人工更新表中non_sname索引統計
在實際情況中,有時候不同索引會比用索引的速度更快,在運用索引查詢的時候,但是sql server工具會自動幫你判斷