SqlServer索引的原理與應用

来源:http://www.cnblogs.com/lj820403/archive/2017/07/29/7253334.html
-Advertisement-
Play Games

索引的概念 索引的用途:我們對數據查詢及處理速度已成為衡量應用系統成敗的標準,而採用索引來加快數據處理速度通常是最普遍採用的優化方法。 索引是什麼:資料庫中的索引類似於一本書的目錄,在一本書中使用目錄可以快速找到你想要的信息,而不需要讀完全書。在資料庫中,資料庫程式使用索引可以重啊到表中的數據,而不 ...


索引的概念

索引的用途:我們對數據查詢及處理速度已成為衡量應用系統成敗的標準,而採用索引來加快數據處理速度通常是最普遍採用的優化方法。

索引是什麼:資料庫中的索引類似於一本書的目錄,在一本書中使用目錄可以快速找到你想要的信息,而不需要讀完全書。在資料庫中,資料庫程式使用索引可以重啊到表中的數據,而不必掃描整個表。書中的目錄是一個字詞以及各字詞所在的頁碼列表,資料庫中的索引是表中的值以及各值存儲位置的列表。

索引的利弊:查詢執行的大部分開銷是I/O,使用索引提高性能的一個主要目標是避免全表掃描,因為全表掃描需要從磁碟上讀取表的每一個數據頁,如果有索引指向數據值,則查詢只需要讀少數次的磁碟就行啦。所以合理的使用索引能加速數據的查詢。但是索引並不總是提高系統的性能,帶索引的表需要在數據庫中占用更多的存儲空間,同樣用來增刪數據的命令運行時間以及維護索引所需的處理時間會更長。所以我們要合理使用索引,及時更新去除次優索引。

數據表的基本結構

一個新表被創建之時,系統將在磁碟中分配一段以8K為單位的連續空間,當欄位的值從記憶體寫入磁碟時,就在這一既定空間隨機保存,當一個 8K用完的時候,資料庫指針會自動分配一個8K的空間。這裡,每個8K空間被稱為一個數據頁(Page),又名頁面或數據頁面,並分配從0-7的頁號, 每個文件的第0頁記錄引導信息,叫文件頭(File header);每8個數據頁(64K)的組合形成擴展區(Extent),稱為擴展。全部數據頁的組合形成堆(Heap)。

SQLS規定行不能跨越數據頁,所以,每行記錄的最大數據量只能為8K。這就是char和varchar這兩種字元串類型容量要限制在8K以內的 原因,存儲超過8K的數據應使用text類型,實際上,text類型的欄位值不能直接錄入和保存,它只是存儲一個指針,指向由若幹8K的文本數據頁所組成 的擴展區,真正的數據正是放在這些數據頁中。 

頁面有空間頁面和數據頁面之分。  

當一個擴展區的8個數據頁中既包含了空間頁面又包括了數據或索引頁面時,稱為混合擴展(Mixed Extent),每張表都以混合擴展開始;反之,稱為一致擴展(Uniform Extent),專門保存數據及索引信息。 

表被創建之時,SQLS在混合擴展中為其分配至少一個數據頁面,隨著數據量的增長,SQLS可即時在混合擴展中分配出7個頁面,當數據超過8個頁面時,則從一致擴展中分配數據頁面。  

空間頁面專門負責數據空間的分配和管理,包括:PFS頁面(Page free space):記錄一個頁面是否已分配、位於混合擴展還是一致擴展以及頁面上還有多少可用空間等信息;GAM頁面(Global allocation map)和SGAM頁面(Secodary global allocation map):用來記錄空閑的擴展或含有空閑頁面的混合擴展的位置。SQLS綜合利用這三種類型的頁面文件在必要時為數據表創建新空間;  

數據頁或索引頁則專門保存數據及索引信息,SQLS使用4種類型的數據頁面來管理表或索引:它們是IAM頁、數據頁、文本/圖像頁和索引頁。 

在WINDOWS中,我們對文件執行的每一步操作,在磁碟上的物理位置只有系統(system)才知道;SQL SERVER沿襲了這種工作方式,在插入數據的過程中,不但每個欄位值在數據頁面中的保存位置是隨機的,而且每個數據頁面在“堆”中的排列位置也只有系統 (system)才知道。  

這是為什麼呢?眾所周知,OS之所以能管理DISK,是因為在系統啟動時首先載入了文件分配表:FAT(File Allocation Table),正是由它管理文件系統並記錄對文件的一切操作,系統才得以正常運行;同理,作為管理系統級的SQL SERVER,也有這樣一張類似FAT的表存在,它就是索引分佈映像頁:IAM(Index Allocation Map)。  

IAM的存在,使SQLS對數據表的物理管理有了可能。  

IAM頁從混合擴展中分配,記錄了8個初始頁面的位置和該擴展區的位置,每個IAM頁面能管理512,000個數據頁面,如果數據量太 大,SQLS也可以增加更多的IAM頁,可以位於文件的任何位置。第一個IAM頁被稱為FirstIAM,其中記錄了以後的IAM頁的位置。  

數據頁和文本/圖像頁互反,前者保存非文本/圖像類型的數據,因為它們都不超過8K的容量,後者則只保存超過8K容量的文本或圖像類型數據。而索 引頁顧名思義,保存的是與索引結構相關的數據信息。瞭解頁面的問題有助我們下一步準確理解SQLS維護索引的方式,如頁拆分、填充因數等。 

頁分裂

一半的數據將保留在老頁面,而另一半將放入新頁面,並且新頁面可能被分配到任何可用的頁。所以,頻繁頁分裂,後果很嚴重,將使物理表產生大量數據碎片,導致直接造成I/O效率的急劇下降,最後,停止SQLS的運行並重建索引將是我們的唯一選擇!

填充因數

索引的一個特性,定義該索引每頁上的可用空間量。FILLFACTOR(填充因數)適應以後表數據的擴展並減小了頁拆分的可能性。填充因數是從0到100的百分比數值,設為100時表示將數據頁填滿。只有當不會對數據進行更改時(例如 只讀表中)才用此設置。值越小則數據頁上的空閑空間越大,這樣可以減少在索引增長過程中進行頁分裂的需要,但這一操作需要占用更多的硬碟空間。填充因數指定不當,會降低資料庫的讀取性能,其降低量與填充因數設置值成反比。

索引的分類

SQL SERVER中有多種索引類型。

按存儲結構區分:“聚集索引(又稱聚類索引,簇集索引)”,“分聚集索引(非聚類索引,非簇集索引)”

按數據唯一性區分:“唯一索引”,“非唯一索引”

按鍵列個數區分:“單列索引”,“多列索引”。

聚集索引

聚集索引是一種對磁碟上實際數據重新組織以按指定的一列或多列值排序。像我們用到的漢語字典,就是一個聚集索引,比如要查“張”,我們自然而然就翻到字典的後面百十頁。然後根據字母順序跟查找出來。這裡用到微軟的平衡二叉樹演算法,即首先把書翻到大概二分之一的位置,如果要找的頁碼比該頁的頁碼小,就把書向前翻到四分之一處,否則,就把書向後翻到四分之三的地方,依此類推,把書頁續分成更小的部分,直至正確的頁碼。

由於聚集索引是給數據排序,不可能有多種排法,所以一個表只能建立一個聚集索引。科學統計建立這樣的索引需要至少相當與該表120%的附加空間,用來存放該表的副本和索引中間頁,但是他的性能幾乎總是比其它索引要快。

由於在聚集索引下,數據在物理上是按序排列在數據頁上的,重覆值也排在一起,因而包含範圍檢查(bentween,<,><=,>=)或使用group by 或order by的查詢時,一旦找到第一個鍵值的行,後面都將是連在一起,不必在進一步的搜索,避免啦大範圍的掃描,可以大大提高查詢速度。

非聚集索引

sqlserver預設情況下建立的索引是非聚集索引,他不重新組織表中的數據,而是對每一行存儲索引列值並用一個指針指向數據所在的頁面。他像漢語字典中的根據‘偏旁部首’查找要找的字,即便對數據不排序,然而他擁有的目錄更像是目錄,對查取數據的效率也是具有的提升空間,而不需要全表掃描。

一個表可以擁有多個非聚集索引,每個非聚集索引根據索引列的不同提供不同的排序順序。

創建索引

語法

複製代碼
CREATE [UNIQUE] [CLUSTERED| NONCLUSTERED ]
INDEX index_name ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
[with[PAD_INDEX][[,]FILLFACTOR=fillfactor]
[[,]IGNORE_DUP_KEY]
[[,]DROP_EXISTING]
[[,]STATISTICS_NORECOMPUTE]
[[,]SORT_IN_TEMPDB]
]
[ ON filegroup ]   
複製代碼

CREATE INDEX命令創建索引各參數說明如下:

UNIQUE:用於指定為表或視圖創建唯一索引,即不允許存在索引值相同的兩行。

CLUSTERED:用於指定創建的索引為聚集索引。

NONCLUSTERED:用於指定創建的索引為非聚集索引。

index_name:用於指定所創建的索引的名稱。

table:用於指定創建索引的表的名稱。

view:用於指定創建索引的視圖的名稱。

ASC|DESC:用於指定具體某個索引列的升序或降序排序方向。

Column:用於指定被索引的列。

PAD_INDEX:用於指定索引中間級中每個頁(節點)上保持開放的空間。

FILLFACTOR = fillfactor:用於指定在創建索引時,每個索引頁的數據占索引頁大小的百分比,fillfactor的值為1到100。

IGNORE_DUP_KEY:用於控制當往包含於一個唯一聚集索引中的列中插入重覆數據時SQL Server所作的反應。

DROP_EXISTING:用於指定應刪除並重新創建已命名的先前存在的聚集索引或者非聚集索引。

STATISTICS_NORECOMPUTE:用於指定過期的索引統計不會自動重新計算。

SORT_IN_TEMPDB:用於指定創建索引時的中間排序結果將存儲在 tempdb 資料庫中。

ON filegroup:用於指定存放索引的文件組。

例子:

複製代碼
--表bigdata創建一個名為idx_mobiel的非聚集索引,索引欄位為mobiel
create index idx_mobiel
on bigdata(mobiel) 


--表bigdata創建一個名為idx_id的唯一聚集索引,索引欄位為id
--要求成批插入數據時忽略重覆值,不重新計算統計信息,填充因數為40
create unique clustered index idx_id
on bigdata(id) 
with pad_index,
fillfactor=40,
ignore_dup_key,
statistics_norecompute
複製代碼

管理索引

複製代碼
Exec sp_helpindex BigData   --查看索引定義

Exec sp_rename 'BigData.idx_mobiel','idx_big_mobiel'  --將索引名由'idx_mobiel' 改為'idx_big_mobiel'

drop index BigData.idx_big_mobiel  --刪除bigdata表中的idx_big_mobiel索引

dbcc showcontig(bigdata,idx_mobiel) --檢查bigdata表中索引idx_mobiel的碎片信息

dbcc indexdefrag(Test,bigdata,idx_mobiel)  --整理test資料庫中bigdata表的索引idx_mobiel上的碎片

update statistics bigdata  --更新bigdata表中的全部索引的統計信息
複製代碼

索引的設計原則

對於一張表來說索引的有無和建立什麼樣的索引,要取決與where字句和Join表達式中。

一般來說建立索引的原則包括以下內容:

  • 系統一般會給逐漸欄位自動建立聚集索引。
  • 有大量重覆值且經常有範圍查詢和排序、分組的列,或者經常頻繁訪問的列,考慮建立聚集索引。
  • 在一個經常做插入操作的表中建立索引,應使用fillfactor(填充因數)來減少頁分裂,同時提高併發度降低死鎖的發生。如果在表為只讀表,填充因數可設為100.
  • 在選擇索引鍵時,儘可能採用小數據類型的列作為鍵以使每個索引頁能容納儘可能多的索引鍵和指針,通過這種方式,可使一個查詢必需遍歷的索引頁面降低到最小,此外,儘可能的使用整數做為鍵值,因為整數的訪問速度最快。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文的測試環境:python 2.7 註:新手學習筆記 當前環境下,直接輸入中文,顯然會報錯 Non-ASCII character '\xe4' in file F:/pythons_environment_files/filecheck.py on line 3 這時候你需要在開頭加上 # _* ...
  • 在調用方法時,程式的執行流程會進入方法的內部,當執行到方法內部的return語句或執行完方法內部的代碼以後,則返回到調用該方法的位置繼續向下執行。 方法調用的語法分為以下兩種: (1)一個類內部的方法調用:指調用以及被調用的方法都在一個類的內部。 (2)不同類之間的方法調用:指調用以及被調用的方法位 ...
  • 枚舉類雖然很簡單,但是卻往往是系統中業務邏輯最集中最複雜的地方。本文將會分享我們項目中基於hibernate的枚舉類使用規範,包含資料庫中枚舉列數據類型、註釋、枚舉列與枚舉類的映射等。 一、枚舉類定義規範 請註意,枚舉類一定要包含一個常量字元串用於說明每一個枚舉值的作用。為什麼一定要放在枚舉類裡面? ...
  • intent 一、介紹 二、通過intent連接button和activity實例 三、四種顯示intent 四種顯示intent ...
  • text-overflow: -o-ellipsis-lastline;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical; ...
  • activity ...
  • Android高效記憶體之讓你的圖片省記憶體 在做記憶體優化的時候,我們發現除瞭解決記憶體泄露問題,剩下的就只有想辦法減少真實的記憶體占用。而在App中,大部分記憶體可能被我們圖片占用了,所以減少圖片的記憶體占用可以帶來直接的效果。 一、一張圖片到底占用多少記憶體 我們先假設我們有一張圖片是600 * 800像素的 ...
  • 1. keytool 命令 1)使用JDK中的一個命令keytool,都有哪些命令呢,使用 keytool -help 進行查看 2)本次使用 keytool -genkeypair 命令生成簽名,查看此命令都有哪些參數keytool -genkeypair -help 發現keytool -gen ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...