广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >SQL Server索引结构的具体使用
  • 810
分享到

SQL Server索引结构的具体使用

2024-04-02 19:04:59 810人浏览 独家记忆
摘要

目录名词介绍索引表数据页索引是数据库的基础,只有先搞明白索引的结构,才能搞明白索引运行的逻辑 本文通过 索引表、数据页、执行计划、io统计、B+Tree 来尽可能的介绍 sql 语句

索引是数据库的基础,只有先搞明白索引的结构,才能搞明白索引运行的逻辑

本文通过 索引表、数据页、执行计划、io统计、B+Tree 来尽可能的介绍 sql 语句中 WHERE 部分,和 SELECT 部分 的运行逻辑

名词介绍

B+Tree:一种数据结构

  • 数据页:数据库保存数据的最小单位。(SQL Server一个数据页的大小是 8K,一个表中所有的数据都被保存到一个个的数据页中)
  • 索引组织表:大白话一张表有聚集索引就是索引组织表(把表中的数据页以 B+Tree 的方式组织起来)
  • 索引表:一个索引对应一张索引表,索引表中每条数据都对应一张数据页。

通过DBCC IND(数据库, 表名, 索引Id) 命令可以获取到表中指定索引的索引表信息

通过DBCC PAGE(数据库, 1, 数据页Id, 3) 命令可以获取到某个数据页中的数据

B+Tree结构

准备数据

DROP TABLE Org_User
-- 创建测试表
CREATE TABLE Org_User(Id INT,UserName NVARCHAR(50),Age INT)
-- 创建聚集索引和非聚集索引
CREATE CLUSTERED INDEX Org_User_Id ON Org_User(Id)
CREATE NONCLUSTERED INDEX Org_User_Name ON Org_User(UserName)

CREATE TABLE #Temp(Id INT)
INSERT INTO #Temp VALUES(1)
INSERT INTO #Temp VALUES(2)
INSERT INTO #Temp VALUES(3)
INSERT INTO #Temp VALUES(4)
INSERT INTO #Temp VALUES(5)
INSERT INTO #Temp VALUES(6)
INSERT INTO #Temp VALUES(7)
INSERT INTO #Temp VALUES(8)
INSERT INTO #Temp VALUES(9)
INSERT INTO #Temp VALUES(10)

-- 批量插入10W条数据
INSERT  INTO dbo.Org_User
SELECT T1.Id, 'UserName_' + CONVERT(NVARCHAR(20), T1.Id) AS 'UserName', T1.Id + 10 AS 'Age' FROM 
(
    SELECT TOP 100000 Id = ROW_NUMBER() OVER (ORDER BY T1.Id)
    FROM #Temp AS T1
    CROSS JOIN #Temp AS T2
    CROSS JOIN #Temp AS T3
    CROSS JOIN #Temp AS T4
    CROSS JOIN #Temp AS T5
    ORDER BY T1.Id
) AS T1


SELECT name, index_id,type_desc FROM SYS.INDEXES WHERE object_id = OBJECT_ID('Org_User');

SELECT  index_id ,
        index_type_desc ,
        index_depth ,
        page_count
FROM    sys.dm_db_index_physical_stats(DB_ID('Core2022'), OBJECT_ID('Org_User'), NULL, NULL, NULL)

在 sys.dm_db_index_physical_stats 这张系统表中

index_depth 表示索引的深度 (对应上图B+Tree就是树的高度)

page_cout 表示索引数据页的数量 (对应上图B+Tree就是叶子节点的数量)

这里获取索引信息主要是为了 index_id

索引表

DBCC IND(Core2022, Org_User, 1)

DROP TABLE dbcc_ind
-- 创建一张表用来保存索引表信息
CREATE TABLE dbcc_ind
(
    PageFID NUMERIC(20),
    PagePID NUMERIC(20),
    IAMFID NUMERIC(20),
    IAMPID NUMERIC(20),
    ObjectID NUMERIC(20),
    IndexID NUMERIC(20),
    PartitionNumber NUMERIC(20),
    PartitionID NUMERIC(20),
    iam_chain_type VARCHAR(100),
    PageType NUMERIC(20),
    IndexLevel NUMERIC(20),
    NextPageFID NUMERIC(20),
    NextPagePID NUMERIC(20),
    PrevPageFID NUMERIC(20),
    PrevPagePID NUMERIC(20)
)

--DROP PROC proc_dbcc_ind
-- 创建存储过程
CREATE PROC proc_dbcc_ind
AS
DBCC IND(Core2022,Org_User,1)

-- 把索引表中的数据批量插入到 dbcc_ind 中
INSERT INTO dbcc_ind
EXEC proc_dbcc_ind
SELECT 
    PagePID, -- 改行数据对应的数据页
    IndexLevel, -- 表示改行数据的级别 0叶子节点,1分支节点,=2根节点,仅限该Demo
    NextPagePID, -- 当前节点的后继节点 (后面的那个数据页)
    PrevPagePID -- 当前节点的前驱节点 (前面的那个数据页)
FROM dbcc_ind
SELECT 
    PagePID,
    IndexLevel,
    NextPagePID,
    PrevPagePID 
FROM dbcc_ind 
WHERE IndexLevel = 0
ORDER BY NextPagePID

对 DBCC IND 中的数据进行一个总结

通过观察叶子节点的数据可以得到,每个节点都有一个前驱指针和后继指针,构成了一个双向链表

通过 IndexLevel 这个字段区分 根节点、分支节点、叶子节点

通过 NextPagePID 和 PrevPagePID 两个字段把相同深度的节点构成了一个双向链表

数据页

DBCC TRACEON(3604) — 打开跟踪标记,不打开的话 DBCC PAGE 只能查看分支节点中的数据,不能查看叶子节点中的数据

根节点

分支节点

叶子节点

非聚集索引的叶子节点

对索引表和根节点对应的数据页,分支节点对应的数据页,叶子节点对应的数据页进行总结

聚集索引

  叶子节点中保存的是 Org_User 表中的数据

  根节点和分支节点中保存的是指向下一级节点的条件

  索引表中同级的节点都有一个前驱和后继指针,这两个指针把同级的节点构建成了一个双向链表

非聚集索引

  根节点和分支节点与聚集索引一直,都是指向下一级节点的条件

  叶子节点有区别包含 创建非聚集索引是指定的Key、指向该行数据实际地址的Key、保证索引唯一的Key

    UserName 就是创建索引时指定的,如果创建时指定多个,这里也会有多个

    Id 这个是指向这行数据真实地址的指针表结构不同这个Key也不一样

      索引组织表:这个Key就是创建聚集索引时指定的 Key

      堆表:就值这个行数据所在堆表的地址

    UNIQUIFIER 如果创建索引时指定该索引时唯一索引,那么这里就不会有这个字段,否则就会有这个字段用来区分重复的数据

通过索引表,找到 Id = 66666 的这行数据所在的数据页    

对上图进行解释

拿着 66666 从根节点指向的数据页开始找

66666 > 36017 所以就跳转到 491 这个数据页

66511 < 66666 ≤ 66669 所以就跳转到 2755 这个数据页

因为 2755 这个数据页已经是叶子节点了,直接在里面搜索 66666

就找到了这一行数据

SET STATISTICS IO ON 
SELECT * FROM Org_User WHERE Id = 66666

回表

因为这条SQL返回的字段是 Select *

非聚集索引里面没有 Age 这个字段

因此根据 UserName_66666 从非聚集索引中找到这条数据之后,根据 Id 到聚集索引里面在查一次,找到 Age 这个字段

覆盖索引

Select Id,UserName 非聚集索引里面这两个字段都有,所以就没有必要在查询聚集索引了

举一个例子

SET STATISTICS IO ON
SELECT * FROM [Org_User] WHERE Id >= 1 AND Id <= 10
SELECT * FROM [Org_User] WHERE Id IN (1,2,3,4,5,6,7,8,9,10)

-- 上面这两个SQL只有在 Id 为 Int 类型的时候才等价,在等价的前提下
-- 第一个SQL的效率要远超于第二个SQL

只有搞明白了索引运行的逻辑,结合执行计划等工具,才能搞明白什么情况下那些SQL更好

谣言:

  COUNT(*) 和 COUNT(列) 谁快,谁慢

  首先这两种写法都不等价 COUNT(*) 是所有的数据 COUNT(列) NULL值不参与运算,所以如果COUNT的某一列中包含了NULL值算出来的数据可能就有问题了

  查询速度

    COUNT(*) 更块

    COUNT(列) 会受偏移量和字段中数据的大小影响

      (通过 SET STATISTICS TIME ON 可以非常简单的得出结论)

  SQL语句 大表写前面,小表写后面

    当前数据库都会对SQL进行优化,所以无所谓谁在前,谁在后

  IN 与 EXISTS 谁好谁坏

    当前数据库都会对SQL进行优化,所以无所谓谁好,谁坏

  这些坑人的谣言还有很多,有些在老版本的数据库是对的,在当前的数据库中已经过时了。

到此这篇关于SQL Server索引结构的具体使用的文章就介绍到这了,更多相关SQL Server 索引结构内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SQL Server索引结构的具体使用

本文链接: https://www.lsjlt.com/news/140483.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SQL Server索引结构的具体使用
    目录名词介绍索引表数据页索引是数据库的基础,只有先搞明白索引的结构,才能搞明白索引运行的逻辑 本文通过 索引表、数据页、执行计划、IO统计、B+Tree 来尽可能的介绍 SQL 语句...
    99+
    2022-11-13
  • 详解SQL Server表和索引存储结构
    本文详细分析了SQL Server中表和索引结构存储的原理以及对于如何加快搜索速度和提高效率等方面做了详细的分析,以下是主要内容。 下图显示了表的存储组织,每张表有一个对应的对象ID,并且包含一个或多个分区...
    99+
    2022-10-18
  • SQL Server中表和索引存储结构的作用是什么
    这篇文章给大家介绍SQL Server中表和索引存储结构的作用是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. 堆所谓堆(heap),就是不含聚集索引的表。堆的 sys.par...
    99+
    2022-10-18
  • SQL Server中的索引怎么使用
    本篇内容主要讲解“SQL Server中的索引怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SQL Server中的索引怎么使用”吧!一、索引的介绍什么是索引?索引是...
    99+
    2023-06-30
  • SQL Server中的索引怎么使用
    在SQL Server中,索引可以提高查询性能,加快数据的检索速度。下面是一些使用索引的常见方法:1. 创建索引:在需要加速查询的列...
    99+
    2023-08-18
    SQL Server
  • MySQL索引查询的具体使用
    目录索引的分类聚簇索引非聚簇索引实战理解我们都知道MySQL的辅助索引可以提升检索效率,但是为什么有的时候,走辅助索引反而不如走主键索引的效率高呢?这里我觉得需要先弄懂辅助索引的底层...
    99+
    2023-05-19
    MySQL索引查询 MySQL索引
  • SQL Server中索引的用法详解
    索引是一种数据结构,用于提高数据库中数据的查询效率。SQL Server中的索引可以分为聚集索引和非聚集索引两种类型。聚集索引决定了...
    99+
    2023-08-17
    SQL Server
  • Mysql中强制索引的具体使用
    目录强制索引使用题外话哪些情况适合建立索引哪些情况不适合建立索引强制索引 强制索引,即指定本次查询使用某个特定的索引,这样就可避免mysql优化器使用低效的索引或者走全表扫描放弃使用索引。(Mysql的优化器并不完全可靠...
    99+
    2023-08-14
    Mysql 强制索引
  • SQL SERVER中常用日期函数的具体使用
    1 GETDATE() 返回当前系统日期 SELECT GETDATE() 2 DATEADD(日期部分,常数,日期) 返回将日期的指定日期部分加常数后的结果返回 ...
    99+
    2022-11-12
  • C语言结构体指针的具体使用
    目录什么是结构体指针?如何访问结构体成员?如何传递结构体指针作为参数?结构体指针数组在 C语言中,结构体指针是一种非常有用的数据类型,它可以让我们更方便地操作结构体。结构体指针可以指...
    99+
    2023-05-20
    C语言结构体指针
  • C语言结构体的具体使用方法
    目录初识C语言结构体1.为什么要有结构体2.结构体的定义2.1结构体类型的定义2.2定义结构体普通变量及访问2.3定义结构体指针变量及访问初识C语言结构体 1.为什么要有结构体 (1...
    99+
    2022-11-12
  • 数据结构之堆的具体使用
    目录堆的概念及结构定义堆堆的初始化插入数据判空删除堆顶的数据获取堆顶数据获取元素个数打印销毁堆Topk问题代码总结堆的概念及结构 定义堆 实现堆的功能首先要定义堆的结构体 typ...
    99+
    2022-11-13
  • SQL Server索引设计基础知识详解使用
    目录一、前言二、索引设计背景知识2.1、索引设计策略包括的任务三、常规索引设计3.1、数据库注意事项3.2、查询注意事项3.3、列注意事项3.4、索引的特征3.5、索引排序顺序设计指南总结一、前言 索引设计不佳和缺少索引...
    99+
    2023-04-03
    SQL Server索引设计 SQL索引设计
  • 怎么用SQL语句查看SQL Server的结构信息
    这篇文章主要介绍“怎么用SQL语句查看SQL Server的结构信息”,在日常操作中,相信很多人在怎么用SQL语句查看SQL Server的结构信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方...
    99+
    2022-10-18
  • Sql Server中聚集索引的作用是什么
    这篇文章将为大家详细讲解有关Sql Server中聚集索引的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一:现象1:无索引的情况  还是老规矩,...
    99+
    2022-10-18
  • 在SQL Server中使用命令调用SSIS包的具体方法
    具体操作步骤如下: 1.首先,当然是要在Business Intelligence中设计好包,并调试通过。 2.然后,有两种方式可以在SQL Server中使用命令运行SSIS包 第...
    99+
    2022-11-15
    sql SSIS包
  • MySQL通过添加索引达到优化SQL的具体操作
    不知道大家之前对类似MySQL通过添加索引达到优化SQL的具体操作的文章有无了解,今天我在这里给大家再简单的讲讲。感兴趣的话就一起来看看正文部分吧,相信看完MySQL通过添加索引达到优化SQL的具体操作你一...
    99+
    2022-10-18
  • Sql Server中非聚集索引的作用是什么
    这篇文章将为大家详细讲解有关Sql Server中非聚集索引的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一:现象先让我们一睹非聚集索引的真容,...
    99+
    2022-10-18
  • Python二进制数据结构Struct的具体使用
    目录二进制数据结构Struct函数与Struct类打包解包字节序指示符缓冲区二进制数据结构Struct 在C/C++语言中,struct被称为结构体。而在Python中,struct是一个专门的库,用于处理字节串与原...
    99+
    2022-06-02
    Python 二进制数据结构Struct Python 二进制数据结构 Python Struct
  • MySQL使用B+树作为索引结构的原因
    这篇文章将为大家详细讲解有关MySQL使用B+树作为索引结构的原因,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、二叉查找树(BST):不平衡二叉查找树(BST,Bin...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作