博客
关于我
SQL Server-索引故事的遥远由来,原来是这样的?(二十八)
阅读量:406 次
发布时间:2019-03-05

本文共 2837 字,大约阅读时间需要 9 分钟。

前言

前段时间工作比较忙,每天回来后总是时不时去写有关ASP.NET Core的文章,无论是项目当中遇到的问题还是自学的内容,我都尽量写得严谨一些,并乐于分享。接下来利用过年的几天时间继续更新SQL Server系列,欢迎继续关注博客和个人公众号。

话题闲聊

关于SQL Server中的索引,我之前已经讲了不少,但为什么还要再来讲一遍呢?主要是因为看到别人的博客或文章时,总会有新的想法或更好的理解方式。虽然看过之后感觉明白了,但过了一段时间再回去看,可能还是停留在了表面。就像SQL Server中的索引,它不仅仅是一个基础性东西,更是性能优化的重要部分。如果没能很好地理解,其他知识点也会很难掌握。所以有时候我会再仔细整理一遍,尽量让自己的理解更深入一些。

前端页面无论做得多么精致,最终离不开数据的支撑。前端能够完美呈现数据只是解决了用户体验的第一步。当用户查看某个页面时,如果数据加载时间过长,即使数据量再大,也可能失去大量用户。这个时候就需要关注数据库数据的优化了,排除其他因素,接下来就进入索引的前世今生。

索引故事

唐代李世民为了让百姓修养生息,打下治理基础,试点设置长安的图书馆。图书馆藏书成千上万,每个书架上的书都没有编排。百姓虽然抱着怀疑的态度去看,但知识分子们还是前来借书。房玄龄负责管理图书馆,助手们不知道书放在哪个书架上的哪一排,花了6小时才找到第一本书。后续排队的人只能等待很长时间。

【SQL Server场景:这就像在表中没有建立主键一样,当需要在表中查找数据时,数据库引擎只能扫描所有表中的每一行来获取想要的那条行数据,导致执行速度非常慢。】

第一批前来的人受益不大,但借书人数量每天都在增加,房玄龄的助手们很快就累坏了。皇帝李世民怪罪下来后,房玄龄只好想办法解决问题。通过对书架上的书进行编号,助手们可以很快找到所需的书。助手们本来累得脸上写满苦逼,听到房玄龄的方案后,脸上的表情却慢慢变成了笑容。

随着时间推移,房玄龄的助手们又遇到一个新问题:有位老太太看到了书名,想要借那本书,但不知道书名的编号。助手们只能逐一检查每个书架,花了一个小时才找到那本书。这个问题困扰了他们几天,直到房玄龄提出创建一个书名目录,并对目录中的书名进行编排。这样一来,借书速度大大提高,来图书馆的人也越来越多。

【SQL Server场景:这就像在Blog表中只有BlogId(主键)建立了聚集索引,而没有其他索引。当我们需要根据BlogName查找数据时,只能扫描所有数据页,导致查询速度很慢。】

通过上面的故事,我们可以看到索引在数据库中的重要性。接下来,我们将从索引的基础知识开始,逐步深入探讨。通过这个故事的梳理,希望大家能更好地理解索引的工作原理,以及如何恰当地创建索引。

索引碎片

通过上述故事,我们已经大致了解了索引的重要性。然而,索引并不是一成不变的。随着数据库中的数据不断插入、更新和删除,索引可能会出现碎片。索引碎片会严重影响查询性能,导致数据库的效率下降。那么,什么是索引碎片呢?索引碎片分为两种类型:

(1)内部索引碎片:当数据页上的数据进行更新或删除时,索引页上的数据以稀疏矩阵的形式分布,导致索引页上的空行增多,从而增加查询的执行时间。

(2)外部索引碎片:当数据页上的数据进行插入或更新时,会导致页拆分和磁盘文件系统上的索引页重新分配,导致数据页或索引页的不连续性。这种碎片会严重降低性能,尤其是当查询结果集的WHERE条件涉及到范围时。

那么,如何判断是否存在索引碎片呢?我们可以使用以下代码来检查 AdventureWorks2012 数据库中的索引碎片情况:

SELECT object_name(dt.object_id) AS TableName, si.name AS IndexName, dt.avg_fragmentation_in_percent AS ExternalFragmentation, dt.avg_page_space_used_in_percent AS InternalFragmentation  FROM (SELECT object_id, index_id, avg_fragmentation_in_percent, avg_page_space_used_in_percent FROM sys.dm_db_index_physical_stats(db_id('AdventureWorks2012'), null, null, null, 'DETAILED') WHERE index_id > 0) AS dt  INNER JOIN sys.indexes si ON si.object_id = dt.object_id AND si.index_id = dt.index_id AND dt.avg_fragmentation_in_percent > 10 AND dt.avg_page_space_used_in_percent < 75  ORDER BY avg_fragmentation_in_percent DESC

通过上面的代码,我们可以查看AdventureWorks2012数据库中存在外部索引碎片和内部索引碎片的情况。规则是:

(1)当ExternalFragmentation > 10时,说明存在外部索引碎片。

(2)当InternalFragmentation < 75时,说明存在内部索引碎片。

当发现存在索引碎片时,应该采取什么措施进行修复呢?我们有两种主要的方法:

(1)通过以下代码重组磁盘索引碎片:

ALTER INDEX ALL ON TableName REORGANIZE

(2)通过以下代码重建磁盘索引碎片:

ALTER INDEX ALL ON TableName REBUILD WITH (FILLFACTOR=90, ONLINE=ON)

当然,我们也可以通过数据库的UI界面来重组和重建索引碎片。那么,什么时候应该进行索引碎片的重组或重建呢?一般来说,当:

当ExternalFragmentation在10-15之间且InternalFragmentation在60-75之间时,应重组索引碎片;

否则,应该重建索引碎片。需要注意的是,当对特定表进行索引重建时,整个表会被加锁,这在重组索引中不会出现。因此,在生产环境中对大表进行索引重建可能会导致长时间的锁定,影响业务操作。SQL Server 2005及以上版本提供了ONLINE参数,可以避免这种情况。

总结

这篇文章主要讲述了索引碎片的概念及其对数据库性能的影响。通过一个历史故事的形式,希望大家能更直观地理解索引的工作原理。接下来的系列文章,我们将开始探讨事务管理和数据库锁机制等高级话题,敬请期待。如有任何问题或建议,请随时联系我。

转载地址:http://thlzz.baihongyu.com/

你可能感兴趣的文章
Node.js安装及环境配置之Windows篇
查看>>
Node.js安装和入门 - 2行代码让你能够启动一个Server
查看>>
node.js安装方法
查看>>
Node.js官网无法正常访问时安装NodeJS的方法
查看>>
node.js模块、包
查看>>
node.js的express框架用法(一)
查看>>
Node.js的交互式解释器(REPL)
查看>>
Node.js的循环与异步问题
查看>>
Node.js高级编程:用Javascript构建可伸缩应用(1)1.1 介绍和安装-安装Node
查看>>
nodejs + socket.io 同时使用http 和 https
查看>>
NodeJS @kubernetes/client-node连接到kubernetes集群的方法
查看>>
NodeJS API简介
查看>>
Nodejs express 获取url参数,post参数的三种方式
查看>>
nodejs http小爬虫
查看>>
nodejs libararies
查看>>
nodejs npm常用命令
查看>>
nodejs npm常用命令
查看>>
Nodejs process.nextTick() 使用详解
查看>>
NodeJS yarn 或 npm如何切换淘宝或国外镜像源
查看>>
nodejs 中间件理解
查看>>