SQL Server 查询优化(2)_索引的遍历与维护

合集下载

sqlserver索引原理 -回复

sqlserver索引原理 -回复

sqlserver索引原理-回复SQL Server索引原理索引是数据库中用于加速数据检索速度的重要组成部分。

在实际应用中,索引的设计与使用是优化数据库性能的关键。

本文将以SQL Server索引原理为主题,以简明扼要的方式逐步解答相关问题。

一、什么是索引?索引是数据库中的一种数据结构,用于快速检索表中的数据。

它类似于书籍的目录,可以根据关键字快速找到所需数据的位置。

在SQL Server中,索引的结构主要包括B-Tree索引和哈希索引。

二、为什么需要索引?1. 提高查询速度:索引可以减少数据库查询的数据量,加快查询速度。

2. 优化性能:索引可以减少数据的物理访问次数,减少磁盘I/O操作,提高数据库的性能。

3. 加强数据完整性:通过索引可以定义唯一约束,保证数据的唯一性。

三、如何创建索引?创建索引可以通过以下两种方式实现:1. 创建表时同时创建索引:在创建表的过程中,可以通过指定表的列为索引列来创建索引。

2. 后期创建索引:在已经创建好的表中,可以使用CREATE INDEX语句来创建索引。

四、SQL Server索引的类型SQL Server中常见的索引类型有:1. 聚簇索引(Clustered Index):按照索引列的值将表中的数据物理排序,一个表只能有一个聚簇索引。

2. 非聚簇索引(Non-clustered Index):创建一个单独的索引结构,其中包含索引列的值和指向实际数据的指针。

3. 唯一索引(Unique Index):保证索引列的唯一性,一个表可以有多个唯一索引。

4. 主键索引(Primary Key Index):一种特殊的唯一索引,用于定义主键约束。

五、索引的原理与工作过程1. B-Tree索引原理:B-Tree是一种多叉树结构,在SQL Server中用于实现索引。

B-Tree索引将索引数据存储在树的节点中,通过不断分割节点来实现数据的快速定位。

每个节点包含一个索引值和指向其他节点的指针,这些指针可以指向其他节点或叶子节点。

sqlsqerver语句优化方法

sqlsqerver语句优化方法

sqlsqerver语句优化方法SQL Server是一种关系型数据库管理系统,可以使用SQL语句对数据进行操作和管理。

优化SQL Server语句可以提高查询和操作数据的效率,使得系统更加高效稳定。

下面列举了10个优化SQL Server语句的方法:1. 使用索引:在查询频繁的列上创建索引,可以加快查询速度。

但是要注意不要过度索引,否则会影响插入和更新操作的性能。

2. 避免使用SELECT *:只选择需要的列,避免不必要的数据传输和处理,提高查询效率。

3. 使用JOIN替代子查询:在进行关联查询时,使用JOIN操作比子查询更高效。

尽量避免在WHERE子句中使用子查询。

4. 使用EXISTS替代IN:在查询中使用EXISTS操作比IN操作更高效。

因为EXISTS只需要找到一个匹配的行就停止了,而IN需要对所有的值进行匹配。

5. 使用UNION替代UNION ALL:如果对多个表进行合并查询时,如果不需要去重,则使用UNION ALL操作比UNION操作更高效。

6. 使用TRUNCATE TABLE替代DELETE:如果要删除表中的所有数据,使用TRUNCATE TABLE操作比DELETE操作更高效。

因为TRUNCATE TABLE不会像DELETE一样逐行删除,而是直接删除整个表的数据。

7. 使用分页查询:在需要分页显示查询结果时,使用OFFSET和FETCH NEXT操作代替传统的使用ROW_NUMBER进行分页查询。

这样可以减少查询的数据量,提高效率。

8. 避免使用CURSOR:使用游标(CURSOR)会增加数据库的负载,降低查询效率。

如果可能的话,应该尽量避免使用游标。

9. 使用参数化查询:使用参数化查询可以减少SQL注入的风险,同时也可以提高查询的效率。

因为参数化查询会对SQL语句进行预编译,可以复用执行计划。

10. 定期维护数据库:定期清理过期数据、重建索引、更新统计信息等维护操作可以提高数据库的性能。

sql server 查看筛选索引规则

sql server 查看筛选索引规则

一、索引的作用和意义索引是数据库中一种特殊的数据结构,用于提高数据库表中数据的检索效率。

通过建立合适的索引,可以加快查询速度,降低数据库的IO 开销,提高数据库的性能。

在 SQL Server 中,可以通过创建和查看索引来优化数据库的查询效率。

二、创建索引的方式在 SQL Server 中,可以通过以下几种方式来创建索引:1. 使用 CREATE INDEX 语句:可以通过这种方式对表中的列创建单列或多列索引。

2. 在SQL Server Management Studio (SSMS) 中使用图形界面:在 SSMS 中可以通过简单的操作来创建和管理索引。

3. 使用 Transact-SQL (T-SQL) 脚本:可以使用 T-SQL 脚本来创建和管理索引,这种方式更加灵活和精细。

三、查询索引的基本信息在 SQL Server 中,可以通过系统视图和动态管理视图来查询索引的基本信息,包括索引的名称、所属表、索引类型、列名等。

常用的系统视图和动态管理视图包括 sys.indexes、sys.index_columns、sys.objects 等。

四、使用系统存储过程查看索引1. sp_helpindex:通过执行 sp_helpindex 存储过程,可以查看指定表的所有索引信息,包括索引名称、索引列、索引类型等。

2. sp_help:通过执行 sp_help 存储过程,可以查看指定表的所有索引信息,包括索引名称、索引列、索引类型等。

五、使用系统函数查询索引的详细信息1. INDEXPROPERTY 函数:通过执行 INDEXPROPERTY 函数,可以查询指定索引的详细信息,包括是否唯一索引、是否聚集索引等。

2. INDEX_COL 函数:通过执行 INDEX_COL 函数,可以查询指定索引的列信息,包括列的顺序、列名等。

六、使用 SQL Server Management Studio 查看索引1. 打开 SQL Server Management Studio 并连接到目标数据库。

SQLServer数据库性能调优技巧

SQLServer数据库性能调优技巧

SQLServer数据库性能调优技巧第一章:SQLServer数据库性能调优概述SQLServer是一种常用的关系型数据库管理系统,在大型企业和云计算环境中广泛应用。

为了确保数据库的高性能和可靠性,进行数据库性能调优非常重要。

本章将介绍SQLServer数据库性能调优的概念和目标。

1.1 数据库性能调优的概念数据库性能调优是指通过分析和优化数据库的结构、查询、索引、存储和配置等方面的问题,以提高数据库系统的效率和性能。

优化数据库性能可以显著提升数据的访问速度、减少系统响应时间和提高数据库的处理能力。

1.2 数据库性能调优的目标数据库性能调优的主要目标是提高数据库的运行效率和用户的体验,具体目标包括:- 提高数据的访问速度:通过合理的查询优化和索引设计,加快数据的检索速度。

- 减少系统响应时间:通过调整数据库配置、优化SQL 查询和提高硬件性能等措施,缩短系统响应时间。

- 提高数据库的处理能力:通过合理的分区设计、并行处理和负载均衡等措施,提高数据库的并发处理能力。

第二章:SQLServer数据库性能调优基础在进行SQLServer数据库性能调优之前,有几个基础概念需要了解,包括数据库的结构、查询执行计划和索引等。

2.1 数据库的结构SQLServer数据库由多个表组成,每个表由多个行和列组成。

表有一定的关系,通过主键和外键来建立关联。

了解数据库的结构对于进行性能调优非常重要。

2.2 查询执行计划查询执行计划是SQLServer数据库执行查询语句时的执行路径和操作过程的详细描述。

通过分析查询执行计划,可以找到潜在的性能问题,并进行相应的优化。

2.3 索引索引是一种特殊的数据库对象,用于加快查询速度。

常见的索引类型包括聚集索引、非聚集索引和全文索引等。

合理设计索引可以提高查询的性能。

第三章:SQLServer数据库性能调优技巧本章将介绍一些常用的SQLServer数据库性能调优技巧,包括查询优化、索引优化、配置优化和硬件优化等。

sqlserver数据库 提高效率方法

sqlserver数据库 提高效率方法

SQL Server 数据库是一种常见的关系型数据库管理系统,它被广泛应用于企业级应用程序和数据管理系统中。

然而,随着数据库规模的增大和日常操作的复杂性增加,数据库的性能和效率往往成为关注的焦点。

提高SQL Server数据库的效率不仅可以显著改善系统的响应速度和稳定性,也可以节约资源和降低成本。

本文将介绍一些提高SQL Server 数据库效率的方法,帮助管理员和开发人员更好地管理和优化数据库系统。

1. 使用合适的索引索引是数据库中用来加快对表中数据的访问速度的结构,它可以通过创建索引来优化查询的性能。

在SQL Server中,通过对经常进行搜索,排序和过滤的数据列创建合适的索引,可以显著提高查询性能。

定期对索引进行维护和优化也是提高数据库效率的关键步骤。

2. 优化查询语句优化SQL查询语句对于提高数据库效率至关重要。

在编写查询语句时,应避免使用全表扫描,尽量减少数据量,避免使用不必要的连接和子查询,合理使用排序和分组等操作,以及避免使用模糊查询和通配符查询等低效操作。

3. 定期备份和恢复定期备份数据库是保障数据库安全的重要手段,同时备份还能够减少数据库维护的风险。

在备份时,管理员应该选择合适的备份策略,并对备份文件进行存储和管理,以确保数据库在出现故障或灾难时能够快速恢复。

4. 使用存储过程和触发器存储过程和触发器是SQL Server中重要的数据库对象,它们可以提高数据库的安全性和可维护性,同时还能减少网络流量和客户端执行开销,提高数据库的效率。

在编写存储过程和触发器时,应遵循一些最佳实践,如避免多次嵌套存储过程和触发器,减少对数据库的锁定和阻塞。

5. 使用物理分区技术SQL Server支持对数据表进行物理分区,这可以帮助管理员更好地管理数据,并根据需求对数据进行调优。

通过物理分区,可以提高查询和数据加载的性能,同时也方便了数据备份和恢复。

总结通过上述方法,可以显著提高SQL Server数据库的性能和效率,使其能够更好地满足企业应用程序和数据管理系统的需求。

sql server索引的用法

sql server索引的用法

sql server索引的用法SQL Server索引是一种用于提高查询性能的数据结构。

它可以加速数据的访问速度,减少查询的响应时间。

使用SQL Server索引的主要目的是加快查询操作的速度。

索引可以按照某列或几列的值来排序,这样查询时可以快速定位到需要的数据,而不必扫描整个表。

以下是SQL Server索引的一些常见用法:1. 创建索引:可以通过CREATE INDEX语句在表中创建索引。

可以选择创建唯一索引、聚簇索引、非聚簇索引等不同类型的索引。

2. 删除索引:可以使用DROP INDEX语句删除表中的索引。

删除不再需要的索引可以减少资源的使用和维护成本。

3. 聚簇索引的使用:聚簇索引是按照表的主键创建的一种索引,它决定了表的物理存储顺序。

使用聚簇索引可以提高主键查询的性能。

4. 非聚簇索引的使用:非聚簇索引是按照非主键列的值来创建的索引。

可以根据查询的需要选择适当的列创建索引,以提高查询速度。

5. 覆盖索引的使用:覆盖索引是指包含了查询所需的数据列的索引。

当查询只需要从索引中获取数据时,可以节省I/O操作,提高查询性能。

6. 索引的优化:可以通过查看查询计划和性能监视器等工具,分析索引的使用情况。

根据需要进行索引优化,如添加新索引,删除无用索引,调整索引的顺序等。

7. 统计信息的更新:SQL Server对索引的查询优化依赖于统计信息。

可以使用UPDATE STATISTICS语句更新索引的统计信息,以提高查询计划的准确性。

需要注意的是,索引并不是越多越好,过多的索引可能会增加写操作的开销和存储空间的占用。

在创建索引时需要权衡查询性能和维护成本,并选择合适的索引策略。

sqlserver 数据库加索引语句-概述说明以及解释

sqlserver 数据库加索引语句-概述说明以及解释

sqlserver 数据库加索引语句-概述说明以及解释1.引言1.1 概述数据库索引是一种重要的数据库对象,用于提高数据库查询性能并加速数据检索过程。

在SQL Server数据库中,索引可以被理解为一种排好序的数据结构,它能够快速定位和访问存储在数据库表中的数据行。

通过在数据库表中创建索引,可以大大降低查询的时间复杂度,提高数据库的响应速度。

本文将重点介绍SQL Server数据库中的索引是什么,为什么要使用索引以及如何在数据库中添加索引,旨在帮助读者更好地理解数据库索引的作用和使用方法。

1.2 文章结构"文章结构"部分将介绍整篇文章的组织和内容安排。

通过本部分,读者将了解到文章的逻辑结构和各个章节的主要内容。

在本文中,我们将首先介绍数据库索引的概念和作用,然后重点讨论在SQL Server数据库中为什么需要使用索引。

接着,我们将详细讲解如何在SQL Server数据库中添加索引,包括创建、管理和优化索引的具体步骤。

通过这样的结构安排,读者可以清晰地了解到数据库索引在SQL Server中的重要性和应用方法,从而更好地运用索引来提升数据库的性能和效率。

1.3 目的本文的目的是帮助读者了解在SQL Server 数据库中如何使用索引来提高查询性能。

通过深入探讨数据库索引的概念、作用和添加方法,读者可以学习到如何利用索引来优化数据库查询操作,提高数据的检索速度和查询效率。

同时,读者也能够了解到索引在数据库中的重要性,以及如何根据实际需求和场景来选择合适的索引类型并进行优化,从而更好地实现数据管理和处理的目的。

通过本文的学习,读者将能够深入了解索引在数据库中的应用及其优势,为数据库的设计和性能优化提供有力的支持。

2.正文2.1 什么是数据库索引数据库索引是一种数据结构,用于快速查找数据库表中的特定数据。

索引类似于书籍的目录,它可以帮助数据库引擎快速找到表中特定列的数据。

通过创建索引,可以大大减少数据库查询的时间,提高数据库的性能。

SQLServer多表查询优化方案总结

SQLServer多表查询优化方案总结

SQLServer多表查询优化⽅案总结SQL Server多表查询的优化⽅案是本⽂我们主要要介绍的内容,本⽂我们给出了优化⽅案和具体的优化实例,接下来就让我们⼀起来了解⼀下这部分内容。

1.执⾏路径ORACLE的这个功能⼤⼤地提⾼了SQL的执⾏性能并节省了内存的使⽤:我们发现,单表数据的统计⽐多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就可能要⼏⼗秒了.这是因为ORACLE只对简单的表提供⾼速缓冲(cache buffering) ,这个功能并不适⽤于多表连接查询..数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越⼤,就可以保留更多的语句,当然被共享的可能性也就越⼤了.2.选择最有效率的表名顺序(记录少的放在后⾯)ORACLE的解析器按照从右到左的顺序处理FROM⼦句中的表名,因此FROM⼦句中写在最后的表(基础表 driving table)将被最先处理. 在FROM⼦句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运⽤排序及合并的⽅式连接它们.⾸先,扫描第⼀个表(FROM⼦句中最后的那个表)并对记录进⾏派序,然后扫描第⼆个表(FROM⼦句中最后第⼆个表),最后将所有从第⼆个表中检索出的记录与第⼀个表中合适记录进⾏合并.例如:表 TAB1 16,384 条记录表 TAB2 1条记录选择TAB2作为基础表 (最好的⽅法)select count(*) from tab1,tab2 执⾏时间0.96秒选择TAB2作为基础表 (不佳的⽅法)select count(*) from tab2,tab1 执⾏时间26.09秒如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引⽤的表.例如: EMP表描述了LOCATION表和CATEGORY表的交集.1. SELECT *2. FROM LOCATION L ,3. CATEGORY C,4. EMP E5. WHERE E.EMP_NO BETWEEN 1000 AND 20006. AND E.CAT_NO = C.CAT_NO7. AND E.LOCN = L.LOCN将⽐下列SQL更有效率1. SELECT *2. FROM EMP E ,3. LOCATION L ,4. CATEGORY C5. WHERE E.CAT_NO = C.CAT_NO6. AND E.LOCN = L.LOCN7. AND E.EMP_NO BETWEEN 1000 AND 20003.WHERE⼦句中的连接顺序(条件细的放在后⾯)ORACLE采⽤⾃下⽽上的顺序解析WHERE⼦句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最⼤数量记录的条件必须写在WHERE⼦句的末尾.例如:(低效,执⾏时间156.3秒)1. SELECT …2. FROM EMP E3. WHERE SAL > 500004. AND JOB = ‘MANAGER’5. AND 25 < (SELECT COUNT(*) FROM EMP6. WHERE MGR=E.EMPNO);7. (⾼效,执⾏时间10.6秒)8. SELECT …9. FROM EMP E10. WHERE 25 < (SELECT COUNT(*) FROM EMP11. WHERE MGR=E.EMPNO)12. AND SAL > 5000013. AND JOB = ‘MANAGER’;4.SELECT⼦句中避免使⽤'* '当你想在SELECT⼦句中列出所有的COLUMN时,使⽤动态SQL列引⽤ '*' 是⼀个⽅便的⽅法.不幸的是,这是⼀个⾮常低效的⽅法. 实际上,ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个⼯作是通过查询数据字典完成的, 这意味着将耗费更多的时间.5.减少访问数据库的次数当执⾏每条SQL语句时, ORACLE在内部执⾏了许多⼯作: 解析SQL语句, 估算索引的利⽤率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的⼯作量.⽅法1 (低效)1. SELECT EMP_NAME , SALARY , GRADE2. FROM EMP3. WHERE EMP_NO = 342;4. SELECT EMP_NAME , SALARY , GRADE5. FROM EMP6. WHERE EMP_NO = 291;⽅法2 (⾼效)1. SELECT A.EMP_NAME , A.SALARY , A.GRADE,2. B.EMP_NAME , B.SALARY , B.GRADE3. FROM EMP A,EMP B4. WHERE A.EMP_NO = 3425. AND B.EMP_NO = 291;6.删除重复记录最⾼效的删除重复记录⽅法 ( 因为使⽤了ROWID)1. DELETE FROM EMP E2. WHERE E.ROWID > (SELECT MIN(X.ROWID)3. FROM EMP X4. WHERE X.EMP_NO = E.EMP_NO);7.⽤TRUNCATE替代DELETE当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) ⽤来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执⾏删除命令之前的状况),⽽当运⽤TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运⾏后,数据不能被恢复.因此很少的资源被调⽤,执⾏时间也会很短.8.尽量多使⽤COMMIT只要有可能,在程序中尽量多使⽤COMMIT, 这样程序的性能得到提⾼,需求也会因为COMMIT所释放的资源⽽减少:COMMIT所释放的资源:a. 回滚段上⽤于恢复数据的信息.b. 被程序语句获得的锁c. redo log buffer 中的空间d. ORACLE为管理上述3种资源中的内部花费(在使⽤COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼)9.减少对表的查询在含有⼦查询的SQL语句中,要特别注意减少对表的查询.例如:低效:1. SELECT TAB_NAME2. FROM TABLES3. WHERE TAB_NAME = ( SELECT TAB_NAME4. FROM TAB_COLUMNS5. WHERE VERSION = 604)6. AND DB_VER= ( SELECT DB_VER7. FROM TAB_COLUMNS8. WHERE VERSION = 604⾼效:1. SELECT TAB_NAME2. FROM TABLES3. WHERE (TAB_NAME,DB_VER)4. = ( SELECT TAB_NAME,DB_VER)5. FROM TAB_COLUMNS6. WHERE VERSION = 604)Update 多个Column 例⼦:低效:1. UPDATE EMP2. SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES),3. SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES)4. WHERE EMP_DEPT = 0020;⾼效:1. UPDATE EMP2. SET (EMP_CAT, SAL_RANGE)3. = (SELECT MAX(CATEGORY) , MAX(SAL_RANGE)4. FROM EMP_CATEGORIES)5. WHERE EMP_DEPT = 0020;10.⽤EXISTS替代IN,⽤NOT EXISTS替代NOT IN在许多基于基础表的查询中,为了满⾜⼀个条件,往往需要对另⼀个表进⾏联接.在这种情况下, 使⽤EXISTS(或NOT EXISTS)通常将提⾼查询的效率.低效:1. SELECT *2. FROM EMP (基础表)3. WHERE EMPNO > 04. AND DEPTNO IN (SELECT DEPTNO5. FROM DEPT6. WHERE LOC = ‘MELB’)⾼效:1. SELECT *2. FROM EMP (基础表)3. WHERE EMPNO > 04. AND EXISTS (SELECT ‘X’5. FROM DEPT6. WHERE DEPT.DEPTNO = EMP.DEPTNO7. AND LOC = ‘MELB’)(相对来说,⽤NOT EXISTS替换NOT IN 将更显著地提⾼效率)在⼦查询中,NOT IN⼦句将执⾏⼀个内部的排序和合并. ⽆论在哪种情况下,NOT IN都是最低效的 (因为它对⼦查询中的表执⾏了⼀个全表遍历). 为了避免使⽤NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.例如:1. SELECT …2. FROM EMP3. WHERE DEPT_NO NOT IN (SELECT DEPT_NO4. FROM DEPT5. WHERE DEPT_CAT='A');为了提⾼效率.改写为:(⽅法⼀: ⾼效)1. SELECT ….2. FROM EMP A,DEPT B3. WHERE A.DEPT_NO = B.DEPT(+)4. AND B.DEPT_NO IS NULL5. AND B.DEPT_CAT(+) = 'A'(⽅法⼆: 最⾼效)1. SELECT ….2. FROM EMP E3. WHERE NOT EXISTS (SELECT 'X'4. FROM DEPT D5. WHERE D.DEPT_NO = E.DEPT_NO6. AND DEPT_CAT = 'A');当然,最⾼效率的⽅法是有表关联.直接两表关系对联的速度是最快的!11.识别'低效执⾏'的SQL语句⽤下列SQL⼯具找出低效SQL:1. SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,2. ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,3. ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,4. SQL_TEXT5. FROM V$SQLAREA6. WHERE EXECUTIONS>07. AND BUFFER_GETS > 08. AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.89. ORDER BY 4 DESC;(虽然⽬前各种关于SQL优化的图形化⼯具层出不穷,但是写出⾃⼰的SQL⼯具来解决问题始终是⼀个最好的⽅法)关于SQL Server多表查询优化⽅案的相关知识就介绍到这⾥了,希望本次的介绍能够对您有所收获!。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、遍历
索引树的每个节点都是一个页面。

索引树有三种类型的节点:根节点、中间节点、叶子节点。

根节点与中间节点一样,只包含下一层节点的入口值与入口指针,它们称为索引节点;
叶子节点包含要遍历的数据,对聚集索引而言数据就是表中数据行,对非聚集索引数据是指索引列值和行书签。

索引的遍历总是从根节点开始,即先根遍历,分为两种:索引扫描和索引查找。

索引扫描是指从索引树的根节点开始,对叶子节点逐个扫描,直至命中所有满足查找条件的数据;
索引查找是指从索引树的根节点开始,按查找值在索引节点中根据路由信息跳转,直至叶子节点以命中数据。

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%时,应该将兄弟节点合并,即分裂的逆操作,但这样可能带来的后果是更频繁的页面合并、分裂,成本更大,所以在数据库系统中通常不进行页面合并操作。

四.更新
4.1、覆盖更新
如果更新操作能够在页内进行原位键值替换,那么就进行覆盖更新。

4.2、非覆盖更新
无法进行覆盖更新时,更新操作被分解为删除和插入操作。

如果非覆盖更新过程中,新的记录比较长,则会在页面分裂的过程中会带来数据行的移动:(1)聚集索引的移动对非聚集索引没有影响,因为非聚集索引中存储的是聚集索引的键值,分裂并不会改变键值;
(2)堆表中的数据页分裂,会在原记录处留下一个前转指针,以告诉非聚集索引去哪里找新的记录;
所以数据行的移动对非聚集索引都不会带来维护的成本,非聚集索引的维护成本来自书签的变化:
(1)聚集索引的键值发生变化或被删除;
(2)堆表中的数据行被删除。

相关文档
最新文档