存儲結構與索引

一、SQL數據存儲的基本介紹

? ? ? ?數據庫中的數據存儲涉及頁(Page)和區(Extent)這兩個概念了。SQL server中數據存儲的基本單位是頁。為數據庫中的數據文件(.mdf或.ndf)分配的磁盤空間可以從邏輯上劃分成頁(從0到n連續編號),磁盤I/O操作在頁級執行。也就是說,SQL Server讀取或寫入數據的最小單位是以8KB為單位的頁。區是8個物理上連續的頁的集合,用來有效地管理頁。如果區內的8個頁屬于同一個表,則這種區稱為統一區;如果區內的8個頁分別屬于至少兩個不同的表,則這種區稱為混合區。頁在SQLScrver中,大小為8KB。這意味著SQL Server數據庫中每MB有128頁。每頁開頭是一個96字節的頁頭,用于存儲有關頁的系統信息。包括頁碼、頁類型、頁的可用空間,以及擁有該頁的對象的分配單元ID。不同類型的數據,存儲在不同類型的頁面里。在數據頁的存儲結構里,每個頁的前面96個字節是頁頭。SQL server通過這96個字節的頁頭和系統表,從邏輯層面上把表的存儲結構管理起來。針對表的存儲結構,SQLserver引入了一些概念:這些概念包括:object(對象)、partition(分區)、Hobt(堆或 B 樹)、allocation_unit(分配單元)。

? ? ? ?表存儲結構的關系如圖所示、每張表會有一個對應的objectID,同時每張表擁有一個或者多個Partition(通常一個Partition對應一個索引)。每個Partition會有一個或者多個Heap or B一Tree(簡稱為Hobt)。Hobt的結構是預留的,通常可以認為,Partition與Hobt是一樣的,PartitionID就是HobtID。每個Hobt會有至多三個分配單元用于存放數據,分別是data(數據)、LOB(大數據字段類型)、Row-Overflow(行溢出)。最頻繁使用的分配單元是Data。如果有LOB數據或者長度超過8000字節的記錄,則可能有另外的LOB分配單元和Row一Overflow分配單元:一個表可以有多個Partition,但是每個Partition以Hobt最多有三個分配單元,每個分配單元可以有許多頁。

?

二、索引對數據存儲的影響

對于每個分配單元內的數據頁,根據表是否有索引,以及索引是聚焦索引或非聚焦索引,其組織方式常見有以下三種:

1、沒有索引

在這種情況下,數據是按堆的結構存儲,只有一個分區,在系統表里,對于這個分區下面的每個分配單元都有一個連接指向Index Allocation Map頁(IAM,索引指引頁),在IAM頁里,描述了區的信息。數據頁之間沒有任何關系,完全依賴IAM頁組織起來。對于這種表的查詢,數據庫會先查詢IAM頁,任何根據其提供的信息,遍歷所有區,將符合條件的頁返回。其結構入下圖所示:

?

PS:表、分區信息等可通過以下系統表查詢

?

1 --查詢表的信息
2 select *from sys.objects where name='test3'
3 --查詢分區信息
4 select *from sys.partitions where object_id='1909581841'
5 --查詢分配單元信息
6 select *from sys.allocation_units where container_id='72057594041335808'
View Code

?

?

2.有非聚集索引但沒聚集索引

?這種情況下,數據依然是以堆結構存儲,不過針對每個非聚集索引,都會有一個對應的partition。對于這個partition下面的每個分配單元,都有一個連接指向根頁。數據頁之間通過前后指針互相關聯,在其結構底層,會有一個連接(文件號、頁號、行號)指向真正的數據。其結構如圖所示:

?

?

3、表有聚集索引

當表有索引時,其索引號為1,它有一個對應的partition,同樣這個partition下的分配單元都會連接到一個根頁,不過對于聚集索引來說,它在葉子節點上直接存儲真正的數據,其結構如下:

?

?三、樣例分析

創建3個樣例表并插入相同的數據,其中test1無索引,test2只有非聚集索引,test3有聚集索引:

 1 use TEST;
 2 
 3 create table test1
 4 (
 5      id int not null,
 6      name char(10) null,
 7      test varchar(max) null,
 8 )
 9 
10 
11 create table test2
12 (
13      id int not null,
14      name char(10) null,
15      test varchar(max) null,
16 )
17  CREATE NONCLUSTERED INDEX NCL_TEST_ID ON test2 (id)
18 
19 
20 create table test3
21 (
22      id int not null primary key,
23      name char(10) null,
24      test varchar(max) null,
25 )
View Code

然后執行以下語句,查詢分配單元情況:

 1 select e.*from sys.objects as a
 2 inner join
 3 sys.partitions as b
 4 on a.object_id=b.object_id
 5 inner join
 6 sys.allocation_units as c
 7 on b.partition_id=c.container_id
 8 inner join
 9 sys.system_internals_allocation_units as e
10 on c.allocation_unit_id=e.allocation_unit_id
11 where a.name='test1'
12 
13 
14 select e.*from sys.objects as a
15 inner join
16 sys.partitions as b
17 on a.object_id=b.object_id
18 inner join
19 sys.allocation_units as c
20 on b.partition_id=c.container_id
21 inner join
22 sys.system_internals_allocation_units as e
23 on c.allocation_unit_id=e.allocation_unit_id
24 where a.name='test2'
25 
26 select e.*from sys.objects as a
27 inner join
28 sys.partitions as b
29 on a.object_id=b.object_id
30 inner join
31 sys.allocation_units as c
32 on b.partition_id=c.container_id
33 inner join
34 sys.system_internals_allocation_units as e
35 on c.allocation_unit_id=e.allocation_unit_id
36 where a.name='test3'
View Code

得到結果如下圖所示:

?

?

?

?

?

?從圖中可以看到,它們都有data、lob這兩種分配單元,無索引的跟只有聚集索引的都是具有相同數量的partition以及頁,有非聚集索引的多了一個partition以及2頁數據來記錄。

PS:可通過以下語句查詢更詳細的partition信息:

1 dbcc ind('test','test1',1)
2 dbcc ind('test','test2',1)
3 dbcc ind('test','test3',1)
4 
5 --dbcc page可查看詳細頁的信息
View Code

四、總結

1.無索引情況下數據以堆結構存儲,開iam頁來引導檢索,對于大表來說,建議建立聚集索引使數據有序化,便于處理;

2.非聚集索引是使用額外的存儲來增加檢索效率,對最底層的數據結構沒影響;

3.聚集索引不會增加額外的存儲,但會使底層的數據有序化;

?

轉載于:https://www.cnblogs.com/9284chc0r0ij/p/10679373.html

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

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

相關文章

面向全球用戶的Teams app之時區篇

我在前兩篇文章里分享了Global Ready的app時會遇到的不同文化的挑戰。這篇我繼續分享在時區方面的挑戰。 時間是最復雜的,最容易出錯的部分。時間復雜的最根本原因是時區問題。 首先,大家都知道,我們地球是圓的,這個意味著如果大…

Linux: Nginx proxy_pass域名解析引發的故障

背景 業務架構: 部署細節:  兩容器均部署在同一機器上,通過 docker-compose 編排,并且通過link方式鏈接。 故障描述 在有次更新代碼時,發現前端能夠打開,但是所有接口請求全是502(Bad GateWay) 故障排查 …

Oracle建立全文索引詳解

Oracle建立全文索引詳解1.全文檢索和普通檢索的區別 不使用Oracle text功能,當然也有很多方法可以在Oracle數據庫中搜索文本,比如INSTR函數和LIKE操作: SELECT *FROM mytext WHERE INSTR (thetext, Oracle) > 0; SELECT * FROM mytext WHE…

面向全球用戶的Teams app之夏令時篇

我在前兩篇文章里分享了Global Ready的teams app時會遇到的不同挑戰。這篇我繼續分享在夏令時方面的挑戰。 夏令時,主要是為了節約能源,英文里通常縮寫成DST(Daylight Saving Time)。一般在天亮早的夏季人為將時間調快一小時,可以使人早起早…

爬取全部的校園新聞

1.從新聞url獲取新聞詳情: 字典,anews 2.從列表頁的url獲取新聞url:列表append(字典) alist 3.生成所頁列表頁的url并獲取全部新聞 :列表extend(列表) allnews *每個同學爬學號尾數開始的10個列表頁 4.設置合理的爬取間隔 import time import…

面向全球用戶的Teams app之合規性篇

我在前兩篇文章里分享了Global Ready的app時會遇到的不同挑戰。這篇我繼續分享在合規性方面的挑戰。 說到合規性compliance,不得不說GDPR標準,當我們發布了一個teams app后,微軟會要求開發人員做一個security self assessment,這…

C進階 - 內存四驅模型

一.內存四驅模型 不知我們是否有讀過 《深入理解 java 虛擬機》這本書,強烈推薦讀一下。在 java 中我們將運行時數據,分為五個區域分別是:程序計數器,java 虛擬機棧,本地方法棧,java 堆,方法區。…

行內元素中去掉文字的上下間距,使得文字所在元素的高度同字體高度一致的方法...

之前在p這類塊元素中的文字,給line-hight1;就可以去掉文字自帶的上下間距, 像這樣: 最近突然發現這個方法在行內塊和塊元素上好使,可當用在span或者a這類內聯元素上都不好使,除了轉為塊元素的方法來去掉上下間距&#…

VSCode的Teams插件

隨著今年在線的Build大會的結束,又是一大波的 Teams 新功能,新工具,新SDK。我接下來幾篇博客就會詳細和大家一一介紹。我今天先從VSCode的插件開始。 打開VS Code,搜索Teams,就可以找到Microsoft Teams Toolkit插件&a…

ADB原理,Wi-Fi連接,常用命令及拓展

Android 開發筆記 onGithub 文章多處鏈接需要科學上網 本文按順序主要講解了ADB的原理,使用Wi-Fi連接設備,ADB常用命令,在Java代碼中執行shell命令,使用ddmlib進行擴展。 ADB的原理 參考 官方文檔 ADB(Android Debug B…

使用Flow快速開發Teams小應用

繼續我的上一篇博客,這篇繼續介紹BUILD大會里的內容:Flow。 Flow是微軟power平臺的一個服務,通過簡單的拖拽就可以完成一個業務邏輯的處理,現在Flow和Teams的結合十分緊密。我們來試一下。 先點擊Teams左邊的Flow菜單。 如果你的…

python正則中如何匹配漢字以及encode(‘utf-8’)和decode(‘utf-8’)的互轉

正則表達式&#xff1a;  [\u2E80-\u9FFF]$ 匹配所有東亞區的語言   [\u4E00-\u9FFF]$ 匹配簡體和繁體   [\u4E00-\u9FA5]$ 匹配簡體   <input type"text" name"username" οnkeyup"valuevalue.replace([\u4E00-\u9FA5]$)"> 正則表…

【區塊鏈】認識區塊鏈的基本概念

2018年區塊鏈技術風卷全球&#xff0c;似乎大家都在談論區塊鏈&#xff0c;那到底什么區塊鏈&#xff0c;區塊鏈到底能干什么&#xff0c;對普通人會有什么影響&#xff0c;很多人還是稀里糊涂&#xff0c;那么就談談我的一些理解吧&#xff0c;拋磚引玉歡迎探討。 我是如何接觸…

Java 分割、合并byte數組

場景&#xff1a;上傳文件較大&#xff0c;把存放文件內容byte數組拆分成小的。下載的時候按照順序合并。 起初覺得挺麻煩的&#xff0c;寫完覺得挺簡單。 切割&#xff1a; /*** 拆分byte數組* * param bytes* 要拆分的數組* param size* 要按幾個組成一…

Java版本的Bot Framework SDK

微軟為了鼓勵Java開發人員開發bot&#xff0c;在上個月推出了Java的Bot SDK v4.6版本&#xff0c;目前還在Preview版本&#xff0c;相信不用多久就可以趕上其他版本了。 我的java還停留在 n 年前的水平&#xff0c;但是處于好奇&#xff0c;決定玩一下這套sdk。 這套sdk目前建…

jquery方法.serializeArray()獲取name和value并轉為json數組

jquery的.serializeArray()方法可以獲取形如以下 [ {name: firstname, value: Hello}, {name: lastname, value: World}, ] name value組成的對象數組&#xff0c;如果我們想得到key為name,value為value的json對象&#xff0c;則如下轉換&#xff1a; var m {}; $.each($(&quo…

Teams Bot 如何使用新的 System.Text.Json 庫

我最近把 LuckyDraw的代碼升級到了 .net core 3.1&#xff0c;當然我也很想使用最新的微軟json庫&#xff0c;System.Text.Json這個庫的性能比之前Newtonsoft.Json速度更快&#xff0c;而且就我本人愛好來說&#xff0c;更加喜歡System.Text.Json的命名&#xff0c;之前一直覺得…

將Teams Template升級到dotnet core 3.1

為了方便開發者開發Teams應用&#xff0c;我在2018年做了dotnet c#的一套模板&#xff0c;這套模塊一共有三種類型&#xff0c;一個是Teams OutgoingWebhook&#xff0c;一個是MessagingExtension&#xff0c;還有一個就是Tab。 今天特地去nuget上看了一下&#xff0c;下載量還…

【動態規劃】cf1034C. Region Separation

質因數分解套路的復雜度分析的動態規劃 題目大意 有一顆$n$個節點有點權的樹&#xff0c;初始整棵樹為$1$號區域&#xff0c;要求滿足下列規則&#xff1a; 除非$i$是最后一個等級&#xff0c;否則每一個$i$級區域都要被分成至少兩個$i1$級區域對于每種等級&#xff0c;每個點必…

阿里大魚短信介入demo分享

下面是關于大魚短信平臺對接的例子&#xff0c;發短信的話&#xff0c;可以用這個&#xff0c;很好用 /*** 通過阿里短信接口發送短信驗證碼* ***/ public class SendSmsUtil {private static Logger logger Logger.getLogger(SendSmsUtil.class);/*** 生成驗證碼* return*/pu…