SQL Server存储引擎
一、遍历索引树的每个节点都是一个页面。索引树有三种类型的节点:根节点、中间节点、叶子节点。(1)根节点与中间节点一样,只包含下一层节点的入口值与入口指针
一、遍历
索引树的每个节点都是一个页面。
索引树有三种类型的节点:根节点、中间节点、叶子节点。
(1) 根节点与中间节点一样,只包含下一层节点的入口值与入口指针,它们称为索引节点;
(2) 叶子节点包含要遍历的数据,服务器空间,对聚集索引而言数据就是表中数据行,对非聚集索引数据是指索引列值和行书签。
索引的遍历总是从根节点开始,即先根遍历,分为两种:索引扫描和索引查找。
(1) 索引扫描,是指从索引树的根节点开始,对叶子节点逐个扫描,直至命中所有满足查找条件的数据;
(2) 索引查找,是指从索引树的根节点开始,按查找值在索引节点中根据路由信息跳转,直至叶子节点以命中数据。
B+树的深度通常小于等于3,计算如下:
以聚集索引为例,简单计算如下:10个INT列宽度总和为40B,假设聚集索引树每一层为二叉,共三层,即2^0+2^1+2^2=1*(1-2^3)/(1-2)=7个页面,4个叶子节点,每个页面8060K可存储8060000/40=201500行,乘以4=806000行,如果是三叉、四叉,那么三层可存储上千万至亿行的数据,当然在数据量达到这个等级时,通常我们会选择表分区,那么B树深度就更不会突破三层了。
所以索引查找的效率是很高的,在查询中应该努力构造索引查找,避免索引扫描。
二、插入
2.1、页空间充足
在已存在数据的表上,创建或重建索引时,可指定填充因子,即在索引树的每个节点上预留一定的空间,供表中后续增加的数据使用。但如果在创建表的时候就创建了索引,并指定了填充因子,这时的填充因子是无用的,数据库系统不会刻意去保留页面的空间。
索引页面有剩余空间的情况如下图:
图1
参考图1,此时向索引树中插入一条索引键值为31的记录,步骤如下:
(1)执行索引键值=31的查找操作,确定该新记录应该插入到叶子节点L2中。
(2)检查L2上是否有足够的空间来存放当前记录,这里假设有足够的空间;
(3)将记录45向后移动,插入索引键值为31的新记录。插入之后,10、30、31、45还是顺序的,香港服务器,如下图:
图2
2.2、页空间不足
参加图2,此时再插入一条索引键值为32的记录,步骤如下:
(1)执行索引键值=32的查找操作,确定该新记录应该插入到叶子节点L2中;
(2)检查L2上是否有足够的空间来存放当前记录,这时发现没有足够的页空间,香港服务器,此时需要进行页面分裂;
(3)向数据库系统申请一个新的页面L4,将L2的一半数据移到L4中,并重新链接叶子的左右节点,如下图:
图3
(4)此时,上层节点也需要生成一个新的叶子节点的指针。这里的上层节点即根节点,如果上层节点没有剩余空间的话,同样也需要进行分裂,这里有剩余空间,如下图:
图4
(5)因为当前记录的键值范围位于页分裂的后一半中,将索引键值为32的新记录插入到L4中,如果键值范围位于前一半,则插入到L2中。如果L4的空间不够存放键值为32的新记录,则L4会继续进行页分裂,这里假设空间足够,插入结束,如下图:
图5
三、删除
3.1、删除叶子节点中的记录
参考图5,删除索引键值为32的记录,步骤如下:
(1)执行索引键值=32的查找操作,确定该记录在L4中;
(2)将索引键值=32的记录标记为虚影,但并不立即释放空间,虚影记录可用于事务回滚、多版本等;
(3)如果此时L4上的虚影记录空间被申请使用,虚影记录就会被擦除;
(4)如果数据页面最后一条记录也被删除,数据页面会被回收;
3.2、删除非叶子节点中的记录
(1)索引节点中的指针被删除时并不是虚影记录,但同样也不释放空间,直到有新的指针插入时,才会进行空间压缩;
(2)堆表中数据行被删除后,页空间不会被回收,即使是空闲分页也还是标识为分配状态,无法被其他对象使用;
注:从理论上讲,在兄弟节点页面空闲空间都小于50%时,应该将兄弟节点合并,即分裂的逆操作,但这样可能带来的后果是更频繁的页面合并、分裂,成本更大,所以在数据库系统中通常不进行页面合并操作,除非rebuild/reorganize索引。
四、更新
4.1、覆盖更新
如果更新操作能够在页内进行原位键值替换,那么就进行覆盖更新。
4.2、非覆盖更新
无法进行覆盖更新时,更新操作被分解为删除和插入操作。
如果非覆盖更新过程中,新的记录比较长,则会在页面分裂的过程中会带来数据行的移动:
(1)聚集索引的移动对非聚集索引没有影响,因为非聚集索引中存储的是聚集索引的键值,分裂并不会改变键值;
(2)堆表中的数据页分裂,会在原记录处留下一个前转指针,以告诉非聚集索引去哪里找新的记录;
所以数据行的移动对非聚集索引都不会带来维护的成本,非聚集索引的维护成本来自书签的变化:
(1)聚集索引的键值发生变化或被删除;
(2)堆表中的数据行被删除。
本文出自 “SQL Server DBA” 博客,请务必保留此出处

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java是一種流行的程式語言,具有強大的檔案處理功能。在Java中,遍歷資料夾並取得所有檔案名稱是一種常見的操作,可以幫助我們快速定位和處理特定目錄下的檔案。本文將介紹如何在Java中實作遍歷資料夾並取得所有檔案名稱的方法,並提供具體的程式碼範例。 1.使用遞歸方法遍歷資料夾我們可以使用遞歸方法遍歷資料夾,遞歸方法是一種自身呼叫自身的方式,可以有效地遍歷資料夾中

PHPglob()函數使用範例:遍歷指定資料夾中的所有文件在PHP開發中,經常需要遍歷指定資料夾中的所有文件,以實現檔案批次操作或讀取。 PHP的glob()函數正是用來實現這種需求的。 glob()函數可以透過指定一個通配符匹配模式,來取得指定資料夾中符合條件的所有檔案的路徑資訊。在這篇文章中,我們將會示範如何使用glob()函數來遍歷指定資料夾中的所有文件

概念差異:Iterator:Iterator是一個接口,代表一個從集合中取得值的迭代器。它提供了MoveNext()、Current()和Reset()等方法,讓你遍歷集合中的元素,並對目前元素進行操作。 Iterable:Iterable也是一個接口,代表一個可迭代的物件。它提供了Iterator()方法,用於傳回一個Iterator對象,以便於遍歷集合中的元素。使用方式:Iterator:要使用Iterator,需要先取得一個Iterator對象,然後呼叫MoveNext()方法來移動到下一

Python3.x中如何使用os模組遍歷目錄中的檔案在Python中,我們可以使用os模組來進行檔案和目錄的操作。 os模組是Python標準庫中的重要模組,提供了許多和作業系統相關的功能。在本文中,我們將介紹如何使用os模組來遍歷一個目錄中的所有檔案。首先,我們需要導入os模組:importos接下來,我們可以使用os.walk()函數來遍歷目錄。

作為一種常用的資料結構,二元樹經常被用來儲存資料、搜尋和排序。遍歷二元樹是非常常見的操作之一。 Python作為一種簡單易用的程式語言,有許多方法可以實作二元樹的遍歷。本文將介紹如何使用Python實現二元樹的前序、中序和後序遍歷。二元樹的基礎在學習二元樹的遍歷之前,我們需要先了解二元樹的基本概念。二元樹由節點組成,每個節點都有一個值和兩個子節點(左子節點和右子

我們得到了用於形成鍊錶的整數值。任務是使用遞歸方法先插入然後遍歷單鍊錶。在末尾遞歸新增節點如果head為NULL→將節點加入head否則加入head(head→next)遞歸遍歷節點如果head為NULL→退出否則列印(head→next)範例輸入−1-2-7-9 -10輸出輸出strong>−鍊錶:1→2→7→9→10→NULL輸入−12-21-17-94-18輸出−鍊錶:12→21→17→94→18→NULL下面程式中使用的方法如下在這種方法中,我們將使用函數新增節點並遍歷單鍊錶並遞

Iterator簡介Iterator是Java中用於遍歷集合的介面。它提供了一組方法,讓您以順序的方式存取集合中的元素。您可以使用Iterator來遍歷List、Set和Map等集合類型。示範程式碼:Listlist=newArrayList();list.add("one");list.add("two");list.add("three");Iteratoriterator=list.iterator();while(iter

在Java中,集合(collection)是一組元素的集合,提供了統一的介面和方法來儲存、檢索和操作這些元素。 Iterator和Iterable是兩個重要的Java接口,它們提供了遍歷集合元素的通用機制。 Iterator介面定義了用於遍歷集合的hasNext()和next()方法。 hasNext()方法用於檢查集合中是否還有未遍歷的元素,next()方法用於傳回目前元素並將其移至下一個元素。 Iterable介面定義了iterator()方法,該方法傳回一個Iterator對象,用於遍歷集合中的元
