从上至下优化

看过一篇文章,印象深刻,里面将数据库查询优化分为四个大的方向

  • 使用钞能力——给DB服务器加物理配置,内存啊,CPU啊,硬盘啊,全上顶配
  • 替换存储系统——根据实际的业务情况选择不同的存储数据库,比如用ES做全文检索
  • 优化存储结构——比如采用分库分表,CQRS(命令查询职责分离),分布式缓存,历史数据归档,数据序列化等
  • 查询语句的优化——增加数据库索引命中率,定期清理数据库索引碎片等

    从上到下成本依次递减,性价比依次升高,今天咱们聊聊Sql Server中基于索引的“查询语句的优化”

索引数据结构

谈到索引,咱们避免不了会想到索引的存储数据结构,目前大多数RDBS(关系型数据库系统)采用B+树来存储索引数据,如果还不是特别清楚啥是B+树的话,这里有传送门点击这里

这里简单概括一下B+树的几个特点:

  • 每个节点可以存储多个元素
  • 所有的非叶子节点只存储关键字信息
  • 所有具体数据都存在叶子结点中
  • 所有的叶子结点中包含了全部元素的信息
  • 所有叶子节点之间都有一个链指针

索引分类

聚集索引

  • 聚集索引根据数据行的键值在表或视图中排序和存储这些数据行。 索引定义中包含聚集索引列。 每个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。
  • 只有当表包含聚集索引时,表中的数据行才按排序顺序存储。 如果表具有聚集索引,则该表称为聚集表。 如果表没有聚集索引,则其数据行存储在一个称为堆的无序结构中。

可以简单理解为数据表中的数据按照既定的顺序进行存储,而这个用来排序的字段就是聚集索引。也可以理解为一个个由Key-Value组成的元素分布在一棵B+树上,Key对应的就是索引,Value对应的就是具体的数据行。

非聚集索引

  • 非聚集索引具有独立于数据行的结构。 非聚集索引包含非聚集索引键值,并且每个键值项都有指向包含该键值的数据行的指针
  • 从非聚集索引中的索引行指向数据行的指针称为行定位器。 行定位器的结构取决于数据页是存储在堆中还是聚集表中。 对于堆,行定位器是指向行的指针。 对于聚集表,行定位器是聚集索引键。

大白话就是非聚集索引中存储的Key-Value,其中Key跟聚集索引一样是索引列,Value根据表是否存在聚集索引来进行区分,如果存在则Value为指向聚集索引键(也就是聚集索引的Key)的指针,不存在,则Value为指向表中数据行的指针。

查询优化

索引命中规则之最左匹配原则

众所周知,我们通常会在高频的where条件所用的字段上建立相关索引,那么我们建立索引以后我们的where查询条件是否命中索引呢?

CREATE NONCLUSTERED INDEX IDEMO ON DEMOTABLE (A ASC,B ASC,C ASC,D ASC);

如上,在表DEMOTABLE中用A,B,C,D四个字段创建了非聚集索引,首先列A必须出现在查询条件中即(A组合),剩下的依次可以为,A,B组合,A,B,C组合,A,B,C,D组合,类似下面这样:

SELECT E,F,G FROM DEMOTABLE WHERE A=1
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2 AND C=3
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2 AND C=3 AND D=4
//不会命中索引
SELECT E,F,G FROM DEMOTABLE WHERE B=2 AND C=3 AND D=4
//部分命中索引,只有条件A=1会命中
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND C=3 AND D=4

索引之覆盖索引

何为覆盖索引?

CREATE NONCLUSTERED INDEX IDEMO ON DEMOTABLE (A ASC,B ASC,C ASC,D ASC) INCLUDE(E,F,G);

上面所建的非聚集索引以上一个创建语句后面多了一个INCLUDE语句,这样做可以减少索引命中以后查询相关列时的回表操作,何谓回表?之前我们讲过在非聚集索引的叶子节点上存放了对应聚集索引的指针,查询在命中非聚集索引的以后要查询非索引列时会根据这个指针去聚集索引上查找相关列,这个动作就是回表;如果我们的非聚集索引上INCLUDE了要查询的列,就可以减少相关查询的回表操作,从而提高查询性能。像下面这条语句就可以完美的规避回表查询。

SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2 AND C=3 AND D=4

索引碎片

索引在建立过程中随着数据量的增加,索引碎片也会越来越多,从而导致即使在索引命中的情况下查询性能可能也不是特别理想,那这些碎片是怎么产生的呢?

  • 外部碎片

新的索引在插入的时候与旧的索引在物理存储位置上不连续,这就产生了外部碎片。

  • 内部碎片

新的索引在插入的时候导致因为索引所占空间大小的变化导致同一页上本可以存储3个索引,现在只能存下2个索引,存储2个索引以后剩下的空间就是内部碎片。

如何处理索引碎片呢?
  • 索引碎片已经很多的情况下

    这种情况我们可以采用索引重新生成或索引重新组织,当然一般来说线上环境都有专门的DBA负责这些事宜,我们只需要知道有这些处理方式就好。
  • 在创建索引的时候

    创建索引时我们可以根据实际的业务场景和索引字段所存信息的大小来适当的添加填充因子(0-100),也可以一定程度上减少索引碎片的产生。如果你还不清楚填充因子的话,可以看看这个

文章就到这里,如有不对的地方,欢迎评论区留言指正,感谢!!

SQL Server查询优化的更多相关文章

  1. SQL Server 查询优化 索引的结构与分类

    一.索引的结构 关系型数据库中以二维表来表达关系模型,表中的数据以页的形式存储在磁盘上,在SQL SERVER中,数据页是磁盘上8k的连续空间,那么,一个表的所有数据页在磁盘上是如何组织的呢?分两种情 ...

  2. SQL Server查询优化方法(查询速度慢的原因很多,常见如下几种) .

    今天看到一位博友的文章,觉得不错,转载一下,希望对大家有帮助,更多文章,请访问:http://blog.haoitsoft.com 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺 ...

  3. SQL Server查询优化器的工作原理

    SQL Server的查询优化器是一个基于成本的优化器.它为一个给定的查询分析出很多的候选的查询计划,并且估算每个候选计划的成本,从而选择一个成本最低的计划进行执行.实际上,因为查询优化器不可能对每一 ...

  4. SQL Server查询优化中的两个选项

    本文中,我们将介绍两个SQL Server中的可用概念,它们是使用SQL Server时值得注意的技术. 1.        OPTIMIZE FOR Unknown SQL Server 2005版 ...

  5. MS SQL Server查询优化方法 查询速度慢的原因很多,常见如下几种

    1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大 ...

  6. SQL Server 查询优化器运行方式

    一.结合实际,谈索引使用的误区 理论的目的是应用.虽然我们刚才列出了何时应使用聚集索引或非聚集索引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析.下面我们将根据在实践中遇到的实际问题 ...

  7. 深入浅出的 SQL Server 查询优化

    目前网络数据库的应用已经成为最为广泛的应用之一了,并且关于数据库的安全性,性能都是企业最为关心的事情.数据库渐渐成为企业的命脉,优化查询就解决了每个关于数据库应用的性能问题,在这里microsoft ...

  8. SQL Server查询优化指南

    1.尽量不要使用is null,否则将导致引擎放弃使用索引而进行全表扫描.2.char是固定长度,速度快,但占空间,varchar不固定长度,不占空间,但速度慢.3.能使用数字类型就不要使用字符,查询 ...

  9. SQL Server 存储中间结果集

    在SQL Server中执行查询时,有一些操作会产生中间结果集,例如:排序操作,Hash Join和Hash Aggregate操作产生的Hash Table,游标等,SQL Server查询优化器使 ...

随机推荐

  1. C# settings 文件基础用法

    原文 自定义设置项类型 Serializable 修饰的枚举,可作为设置项类型 [Serializable] public enum DeviceBrand { None = 0, [Descript ...

  2. MongoDB 常用启动参数

    每日一句 Once you choose your way of life, be brave to stick it out and never return. 生活的道路一旦选定,就要勇敢地走到底 ...

  3. elementUI 函数自定义传参

    <div v-for="(item,i) in ruleContent" :key="i"> <!-- eg:想通过循环将[i]传进函数rul ...

  4. [XJOI3529] 左右

    题目链接:左右 Description 给你一个s数组,一个t数组,你可以对s数组执行以下两种操作 L 操作:每个数等于其左边的数加上自己 R 操作:每个数等于其右边的数加上自己 第一个数的左边是最后 ...

  5. 设置C#启动进程但不显示命令行窗口

    设置一下Process类型相关的配置属性即可,直接上代码. //记得引入命名空间 //using System.Diagnostics; //获得当前环境的基路径 string basePath = ...

  6. 剖析 SPI 在 Spring 中的应用

    vivo 互联网服务器团队 - Ma Jian 一.概述 SPI(Service Provider Interface),是Java内置的一种服务提供发现机制,可以用来提高框架的扩展性,主要用于框架的 ...

  7. 5G的发布加快了智慧城市/三维物联网等行业的发展

    最近很多人发现自己的5G手机突然没了5G信号,难道是美国搞的鬼? 不不不,这其实是因为5G的NSA基站被撤站了,官方已经做了部署,要大力推进SA网络建设.所以之前支持NSA模式的5G手机,现在都成了4 ...

  8. UiPath循环活动While的介绍和使用

    一.While循环的介绍 先判断条件是否满足, 如果满足, 再执行循环体, 直到判断条件不满足,则跳出循环 二.While循环在UiPath中的使用 1. 打开设计器,在设计库中新建一个Flowcha ...

  9. Json多层级动态结构数据解析

    一.工具 (1)GSON Google Gson是一个简单的基于Java的库,用于将Java对象序列化为JSON,反之亦然. 它是由Google开发的一个开源库. 以下几点说明为什么应该使用这个库 - ...

  10. VScode中配置Java环境

    vscode 中配置Java环境 转载说明:本篇文档原作者[@火星动力猿],文档出处来自哔哩哔哩-[教程]VScode中配置Java运行环境 转载请在开头或显眼位置标注转载信息. 1.下载VScode ...