首页 > 数据库 >SQL Server查询优化

SQL Server查询优化

时间:2022-08-25 00:59:42浏览次数:88  
标签:存储 聚集 查询 ASC 索引 SQL DEMOTABLE Server

从上至下优化

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

  • 使用钞能力——给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),也可以一定程度上减少索引碎片的产生。如果你还不清楚填充因子的话,可以看看这个

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

标签:存储,聚集,查询,ASC,索引,SQL,DEMOTABLE,Server
From: https://www.cnblogs.com/wl-blog/p/16622839.html

相关文章

  • 学长告诉我,大厂MySQL都是通过SSH连接的
    大家好,我是咔咔 不期速成,日拱一卒一、背景之前待的几个公司,数据库、服务器权限都是给所有后端直接拉满的,但也会出现员工离职的情况,每次有人离职时都需要改数据库密码、......
  • 基于.NET6、FreeSql、若依UI、LayUI、Bootstrap构建插件式的CMS
    近几年,.net生态日益强大,特别是跨平台技术,性能提升,那真的是强大无比。为了日常能够快速开发,笔者基于基于.NET6、FreeSql、若依UI、LayUI、Bootstrap构建插件式的CMS,请大家......
  • MySQL索引连环问
    MySQL索引连环问什么是索引?索引类似于书本的目录,是存储引擎用于提高数据库表的访问速度的一种数据结构。数据是存储在磁盘上的,查询数据时,如果没有索引,会加载所有的数据......
  • C++地铁线路查询
    C++地铁线路查询问题描述:当一个用户从甲地到乙地时,由于不同需求,就有不同的交通路线,有人希望以最短距离到达,有人希望用最少的换乘次数等。请编写一北京地铁线路查询系统,......
  • MySQL学习
    MySQL学习01数据库的基本概念1.数据库的英文单词:DataBase简称:DB2.什么是数据库*用于存储和管理的仓库3.数据库的特点:*1.持久化存储数据。其实数据库就是一个......
  • java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or re
        这种报错主要是时区没有设置好,1.在数据库后面“?”加上:useSSL=true&characterEncoding=UTF-8&useUnicode=true&serverTimezone=GMT2.在旁边datab......
  • mysql按日期分组(group by)查询统计的时候,没有数据补0的解决办法。
    echarts折线图所需要的数据时间坐标是连续的,但数据库的数据在没有某天的数据的时候查出来的是不连续的解决之前的查询SELECTSUM(amount_data)num,group_codecode,p......
  • mysql设计省市区数据表
    设计成一张表CREATETABLE`region`( `region_id`varchar(10)NOTNULLCOMMENT'地区主键编号', `region_name`varchar(50)NOTNULLCOMMENT'地区名称', `reg......
  • 图解Mysql七种连接
    图解Mysql七种连接1导入数据左边是员工表,右边是部门表2内连接结论:内连接会查询出两个表共有的数据#内连接SELECT*FROMtbl_deptaINNERJOINtbl_emp......
  • MySQL基础使用命令
    0.MySQL服务的启动和停止Windows下:#以管理员身份运行命令提示符输入如下命令#启动MySQL服务命令:netstartMySQL服务名#停止MySQL服务命令:netstopMySQL......