SQL Server聚集索引的選擇

先聲明文章非原創,摘自博客園:http://www.cnblogs.com/CareySon/archive/2012/03/06/2381582.html

簡介

?? 在SQL Server中,數據是按頁進行存放的。而為表加上聚集索引后,SQL Server對于數據的查找就是按照聚集索引的列作為關鍵字進行了。因此對于聚集索引的選擇對性能的影響就變的十分重要了。本文旨在從性能角度來談聚集索引的選擇,但這僅僅是從性能方面考慮。對于有特殊業務要求的表,則需要按實際情況進行選擇。

一、聚集索引所在列或列的組合最好是唯一的

?? 這個原因需要從數據的存放原理來談。在SQL Server中,數據的存放方式并不是以行(Row)為單位,而是以頁為單位。因此,在查找數據時,SQL Server查找的最小單位實際上是頁。也就是說即使你只查找一行很小的數據,SQL Server也會將整個頁查找出來,放在緩沖池中。

? 每一個頁的大小是8K。每個頁都會有一個對于SQL Server來說的物理地址。這個地址的寫法就是文件號:頁號(理解文件號需要你對文件和文件組有所理解)。比如第一個文件的第50頁。則頁號為:1:50。當表沒有聚集索引時,表中的數據頁是以堆(Heap)進行存放的,在頁的基礎上,SQL Server通過一個額外的行號來確定每一行,這也是傳說中的RID。RID是文件號:頁號:行號來進行表示的,假設這一行在起前面所說的頁中的第5行,則RID表示為1:50:5,如圖1所示:

? 從RID的概念來看,RID不僅僅是SQL Server唯一確定每一行的數據,也是存放行的存放位置。當頁通過堆(Heap)進行組織時,頁很少進行移動。

? 而當表上建立索引時,表中的頁按照B樹進行組織。此時,SQL Server尋找行不再是按RID進行查找,轉而使用了關鍵字,也就是聚集索引的列作為關鍵字進行查找。假設圖1的表中,我們設置DepartmentID列作為聚集索引列。則B樹的非葉子節點的行中只包含了DepartmentID和指向下一層結點的書簽(BookMark)。

? 而當我們創建的聚集索引的值不唯一時,SQL Server則無法僅僅通過聚集索引列(也就是關鍵字)唯一確定一行。此時,為了實現對每一行的唯一區分,則需要SQL Server為相同值的聚集索引生成一個額外的標示信息進行區分,這也是所謂的uniquifiers。而使用了uniquifier后,對性能產生的影響分為如下部分:

1、SQL Server必須在插入或者更新時對現在的數據進行判讀是否和現有的鍵重復,如果重復,則需要生成uniqifier,這個是一筆額外開銷。

2、因為需要對相同值的鍵添加額外的uniquifier來區分,因此鍵的大小被額外的增加了。因此無論是葉子節點和非葉子節點,都需要更多的頁進行存儲。從而還影響到非聚集索引,使得非聚集索引的書簽列變大,從而使得非聚集索引也需要進行更多的頁進行存儲。

下面我們進行測試,創建一個測試表,創建聚集索引。插入10W條測試,其中每2條一重復,如圖2所示。

--創建測試表
create table [dbo].[TestP]
([id] int,[Name] varchar(100)
)
go--在id上創建聚集索引
create clustered index testp_cindex on TestP(id)
go
--插入10W條數據測試,每2條一重復
begin tran
declare  @index int
set @index=0
while(@index<100000)
begin insert into dbo.TestP(id,Name)values(@index,'測試數據')insert into dbo.TestP(id,Name)values(@index,'測試數據')
set @index=@index+1
end
commitexec sp_spaceused 'TestP'

我們插入了測試數據
此時,我們來查看這個表所占的頁數,如圖3所示。

插入重復鍵后10W數據占了359頁

我們再次插入10W不重復的數據,如圖所示

??? 此時,所占頁數縮減為335頁,如圖5所示。

???????? 因此,推薦聚集索引所在列使用唯一鍵。

二、最好使用窄列或窄列組合作為聚集索引列

??? 這個道理和上面減少頁的原理一樣,窄列使得鍵的大小變小。使得聚集索引的非葉子節點減少,而非聚集索引的書簽變小,從而葉子節點頁變得更少。最終提高了性能。

?

三、使用值很少變動的列或列的組合作為聚集索引列

??? 在前面我們知道。當為表創建聚集索引后。SQL Server按照鍵查找行。因為在B數中,數據是有序的,所以當聚集索引鍵發生改變時,不僅僅需要改變值本身,還需要改變這個鍵所在行的位置(RID),因此有可能使得行從一頁移動到另一頁。從而達到有序。因此會帶來如下問題:

  • ??? 行從一頁移動到另一頁,這個操作是需要開銷的,不僅如此,這個操作還可能影響到其他行,使得其他行也需要移動位置,有可能產生分頁
  • ??? 行在頁之間的移動會產生索引碎片
  • ??? 鍵的改變會影響到非聚集索引,使得非聚集索引的書簽也需要改變,這又是一筆額外的開銷

???? 這也就是為什么很多表創建一列與數據本身無關的列作為主鍵比如AdventureWorks數據庫中的Person.Address表,使用AddressID這個和數據本身無關的列作為聚集索引列,如圖6所示。而使用AddressLine1作為主鍵的話,員工地址的變動則可能造成上面列表的問題。

??? 6

??? 圖6.創建和數據本身無關的一列作為聚集索引列

?

四、最好使用自增列作為聚集索引列

??? 這個建議也同樣推薦創建一個和數據本身無關的自增列作為聚集索引列。我們知道,如果新添加進來的數據如果聚集索引列需要插入當前有序的B樹中,則需要移動其它的行來給新插入的行騰出位置。因此可能會造成分頁和索引碎片。同樣的,還會造成修改非聚集索引的額外負擔。而使用自增列,新行的插入則會大大的減少分頁和碎片。

?? 最近我碰到過一個情況。一個表每隔幾個月性能就奇慢無比,初步查看是由于有大量的索引碎片。可是每隔幾個月重建一次索引讓我無比厭煩。最終我發現,問題是由于當時設計數據庫的人員將聚集索引建在了GUID上,而GUID是隨機生成的,則可能插入到表的任何位置,從而大大增加了碎片的數量。因此造成上面這種情況。

?

總結

??? 本文簡單介紹了SQL Server存儲的原理和應該規避的幾種聚集索引建立情況,但這僅僅是從性能的角度來談聚集索引的選擇。對于聚集索引的選擇,還是需要全面的考慮進行決定。

?

?

?

轉載于:https://www.cnblogs.com/zhijianliutang/archive/2012/05/16/2505552.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260825.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260825.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260825.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c++突破網關屏蔽_為什么加了屏蔽罩,測試效果反而不好?

來自專治PCB疑難雜癥微信群群友(群友突破1200人啦&#xff0c;文末添加楊老師微信號&#xff0c;可添加入群)的問題討論&#xff1a;設計時我加了屏蔽罩&#xff0c;結果在測試的時候不加屏蔽罩的效果要比加了屏蔽罩的效果好&#xff0c;這是為何&#xff1f;跟PCB設計的屏蔽罩…

第3章 Python 數字圖像處理(DIP) - 灰度變換與空間濾波6 - 分段線性變換 - 比特平面分層

目錄比特平面分層比特平面分層 在一幅256級灰度圖像中&#xff0c;圖像的值是由8比特&#xff08;1字節&#xff09;組成的 def convert_bin(data, n):"""convert decimal to binary, return n th bit, 0 if bit value 0 else 1""" #---------…

與眾不同 windows phone (5) - Chooser(選擇器)

與眾不同 windows phone (5) - Chooser&#xff08;選擇器&#xff09; 原文:與眾不同 windows phone (5) - Chooser&#xff08;選擇器&#xff09;[索引頁][源碼下載] 與眾不同 windows phone (5) - Chooser&#xff08;選擇器&#xff09;作者&#xff1a;webabcd介紹與眾不…

iOS GCD

from&#xff1a;http://www.cnblogs.com/dsxniubility/p/4296937.html 一般&#xff1a; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 耗時操作dispatch_async(dispatch_get_main_queue(), ^{// 更新UI});}); 本文是對以往學習的多線…

c++和java哪個難_2020 年 11 月編程語言排行榜,Python 超越 Java ?

來源&#xff1a;tiobe.com/tiobe-index/November-2020TIOBE 2020 年 11 月份的編程語言排行榜已經公布&#xff0c;官方的標題是&#xff1a;Python 勢如破竹&#xff0c;超越 Java。題外話: 目前小哈正在個人博客(新搭建的網站&#xff0c;域名就是犬小哈的拼音) www.quanxia…

C# 溫故而知新:Stream篇(七)

C# 溫故而知新&#xff1a;Stream篇&#xff08;七&#xff09; NetworkStream 目錄&#xff1a; NetworkStream的作用簡單介紹下TCP/IP 協議和相關層次簡單說明下 TCP和UDP的區別簡單介紹下套接字&#xff08;Socket&#xff09;的概念簡單介紹下TcpClient,TcpListener,IPEndP…

第3章 Python 數字圖像處理(DIP) - 灰度變換與空間濾波7 - 直方圖處理 - 直方圖、歸一化直方圖

目錄直方圖處理直方圖處理 令rk,k0,1,2,…,L?1r_k, k0, 1, 2, \dots, L-1rk?,k0,1,2,…,L?1表于一幅LLL級灰度數字圖像f(x,y)f(x,y)f(x,y)的灰度。fff的非歸一化直方圖定義為&#xff1a; h(rk)nk,k0,1,2,…,L?1(3.6)h(r_{k}) n_{k}, \quad k 0, 1, 2, \dots, L-1 \tag{…

Xamarin Android提示找不到資源屬性定義

為什么80%的碼農都做不了架構師&#xff1f;>>> Xamarin Android提示找不到資源屬性定義 錯誤信息&#xff1a;”Resource.Attribute”未包含”actonBarSize”的定義 Xamarin Android經常會出現找不到資源屬性的錯誤。遇到這種問題&#xff0c;建議先清理解決方法和…

Google Chrome保存插件方法

1、拷貝下面地址到記事本 https://clients2.google.com/service/update2/crx?responseredirect&xid%3D~~~~%26uc 2、打開插件所在的頁面&#xff0c;拷貝插件地址到記事本 如&#xff1a;https://chrome.google.com/webstore/detail/axure-rp-extension-for-ch/dogkpdfckl…

java web項目_[適合初中級Java程序員修煉手冊從0搭建整個Web項目](二)

前言文本已收錄至我的GitHub倉庫&#xff0c;歡迎Star&#xff1a;https://github.com/bin392328206種一棵樹最好的時間是十年前&#xff0c;其次是現在six-finger-web一個Web后端框架的輪子從處理Http請求【基于Netty的請求級Web服務器】 到mvc【接口封裝轉發)】&#xff0c;再…

MapReduce操作HBase

運行HBase時常會遇到個錯誤&#xff0c;我就有這樣的經歷。 ERROR: org.apache.hadoop.hbase.MasterNotRunningException: Retried 7 times 檢查日志&#xff1a;org.apache.hadoop.ipc.RPC$VersionMismatch: Protocol org.apache.hadoop.hdfs.protocol.ClientProtocol versio…

轉 ABAP_ALV_Function方式與OO方式(較為簡單、普通的ALV)

ABAP_ALV_Function方式與OO方式(較為簡單、普通的ALV) 分類&#xff1a; SAP ABAP2013-01-31 09:58 1511人閱讀 評論(0) 收藏 舉報目錄 一、ALV簡介 1、簡介 2、ALV_GRID介紹 3、其它描述 二、開發ALV的基本流程 三、ALV相關開發細節 1、標準ALV與對象ALV的共同開發細節 2、標準…

MAC OS X 1.1 El Capitan安裝方法與步驟

2019獨角獸企業重金招聘Python工程師標準>>> 蘋果公司發布了最新的Mac系統El Capitan,我也跟風安裝了, 昨天試了一天終于算是安裝成功了. ###電腦配置: CPU: E3-1230 v2 主板: 技嘉B75M D3V 顯卡: 微星6850 聲卡: Realtek ALC887 鍵盤: Noppoo 84鍵機械鍵盤 ###下載…

vp與vs聯合開發-網口通信(socket)

Socket通信是一種在網絡中進行進程間通信的機制。它使用了一種稱為套接字&#xff08;Socket&#xff09;的編程接口&#xff0c;通過該接口可以創建、連接、發送和接收數據等操作。 Socket通信中&#xff0c;有兩個主要的角色&#xff1a;服務器和客戶端。服務器負責監聽指定…

第3章 Python 數字圖像處理(DIP) - 灰度變換與空間濾波8 - 直方圖處理 - 直方圖均衡化(全局直方圖均衡化)

直方圖均衡化 灰度映射函數&#xff1a; sT(r),0≤r≤L?1(3.8)s T(r), \quad 0\leq r \leq L -1 \tag{3.8}sT(r),0≤r≤L?1(3.8) 假設&#xff1a; (1) T(r)T(r)T(r)在區間0≤r≤L?10 \leq{r} \leq{L-1}0≤r≤L?1 上是一個單調遞增函數。 (2) 對于0≤r≤L?10 \leq{r} …

python 元組和列表區別_Python干貨整理:一分鐘了解元組與列表使用與區別

元組是 Python 對象的集合&#xff0c;跟列表十分相似。下面進行簡單的對比。列表與元組1、python中的列表list是變量&#xff0c;而元組tuple是常量。列表&#xff1a;是使用方括號[]&#xff0c;元組&#xff1a;則是使用圓括號()2、兩者都可以使用索引讀取值列表1.列表中的a…

JS拖拽,移動與拉伸

上次做的簡單的拖拽&#xff1a;javascript簡單拖拽練習(鼠標事件 mousedown mousemove mouseup) 這次增加了一些相關的功能&#xff0c;增加四個角的拉伸改變寬度&#xff0c;主要還是用到一些簡單的坐標位置計算&#xff0c;沒有什么技術難度&#xff0c;熟練了一下自己對拖拽…

關于release后retainCount還是1的問題

轉自&#xff1a;http://www.cocoachina.com/bbs/read.php?tid175523 realse之后再調用還能調用的的問題&#xff0c;我做了這么多年也是經常遇到&#xff0c;也曾經試圖尋找原因&#xff0c; 就像6樓說的&#xff0c;很多時候都會出現realse過后還能調用的現象。而且對象不是…

Maven for Eclipse 第二章 ——安裝 m2eclipse插件

m2eclipse 是一個提供了 Maven 與 Eclipse 整合的插件。它的意圖是橋接上 Maven 和 Eclipse 之間的缺口。通過 Maven 原型提供的簡單直白的接口創建項目&#xff0c;它使 Maven 在 IDE 中非常容易使用。下面是m2eclipse 提供的一些特性。 創建和導入 Maven 項目在 Eclipse 運行…

第3章 Python 數字圖像處理(DIP) - 灰度變換與空間濾波9 - 直方圖處理 - 直方圖匹配(規定化)灰度圖像,彩色圖像都適用

直方圖匹配&#xff08;規定化&#xff09; 連續灰度 sT(r)(L?1)∫0rpr(w)dw(3.17)s T(r) (L-1) \int_{0}^{r} p_r(w) \text{d} w \tag{3.17} sT(r)(L?1)∫0r?pr?(w)dw(3.17) 定義關于變量zzz的一個函數GGG&#xff0c;它具有如下性質&#xff1a; G(z)(L?1)∫0zpz(v)d…