一、T-SQL执行过程

sql server 索引 执行计划 索引的执行计划_非聚集索引

 

sql语句在执行的时候----经过很多个步骤:     取数据----------------------内存(缓存)------------Redis-------------数据库-------------持久化到硬盘---------------一定是保存在硬盘中;

 

 二、数据库存储机制

1、数据页 在数据库中,通过数据页保存数据----数据页包含8Kb容量; 数据页又在存储区域; 一个存储区域包含8个数据页--保存简单类型 varchar(8000) 如果数据大于8Kb text,img-----肯定大于8000

2、文本图像页

3、管理数据页(首页)

4、索引页  

数据页,存储区域---体积大---索引页相对轻巧----查询快;通过索引查询数据----提升性能 正因为索引页是独立出来----索引需要单独维护他;-----在增加----删除数据的时候----索引页需要调整; 索引----增强查询效率-----查询快,增删改慢;

sql server 索引 执行计划 索引的执行计划_数据库优化设计_02

sql server 索引 执行计划 索引的执行计划_聚集索引_03

sql server 索引 执行计划 索引的执行计划_数据库优化设计_04

sql server 索引 执行计划 索引的执行计划_数据库优化设计_05

 

 

 

 

 三、索引

索引是相对于表而言的。。

1、聚集索引 把类似的数据存储在邻近的地方-----自动排序-----本质就是排序---在一个表中,只能有一个聚集索引,但 是可以一个聚集索引包含多个列

  聚集索引的更新-----需要调整数据在存储区域的摆放位置----千万不要 在你们的正式环境上,随意是去修改索引----一般在非高峰期,去更新索引;

好处:需要排序的查询----快 根据索引列来查询范围----先扫描索引---然后确定数据---快          聚集索引像什么? 类似于新华字典中拼音查字法~----拼音查字法----先通过首字母---确定拼音----页码---直达目标---直接找到 某一个汉字在哪一页; 有一本字典:前面的拼音和部首部分给遗失了; 如果要查询某一个字:从第一页开始; 啊; 类似于没有任何索引的数据表;

2.非聚集索引: 数据不是连续摆放;索引页中保存的索引---记录数据的具体位置;没有排序了; 创建好索引----有限通过索引字段去查询就可以了;非聚集索引,一个表可以有多个 类似于新华字典中偏旁部首查字法

---- 关于索引的一些建议:

1.索引不是越多越好----不好太多

2.在查询条件中出现的比较频繁的字段---建议建立具体索引 在Where后面经常出现的字段

3.主键都会建立索引----主键必须建立索引,(根据实际情况选择主键类型,如果是in--聚集索引, guid-- 非聚集索引)

4.外键也需要建立索引

5.Order by /group by distinct 如果查询频繁,建议建立索引

6.如果重复的数据太多----就没有必要建立索引---性别----0---1--3

7.text,img不要建立索

8.datetime 建议使用索引 查询建议: 尽量不要使用* 查询,尽量把带有所有的字段,放在查询中

 四、执行计划----非常重要

      在执行Sql语句的时候,经过分析,给我们定制一个相对较好的执行方案;在这个方案中,我们可以看到 这个Sql语句在执行的时候,所需要的各种资源信息;展示的结果,是自行过程中,所有消耗的一个清 单;

执行计划信息

1、连线;越粗表示扫描影响的行数愈多。---性能越差

2、Actual Number of Rows 扫描中实际影响的的行数。

3、Estimated Number of Rows 预估扫描影响的行数。

4、Estimated row size 操作符生成的行的估计大小(字节)。

5、Estimated Data Size 预估影响的数据的大小。

常见场景:

1、Table Scan(表扫描) 当表中没有聚集索引,又没有合适索引的情况下,会出现这个操作。这个操作是很耗性能的,他的出现 也意味着优化器要遍历整张表去查找你所需要的数据。

 

SELECT * FROM [CustomerDB].[dbo].[Company]

 

2、Clustered Index Scan(聚集索引扫描)、Index Scan(非聚集索引扫描) 一个聚集索引扫描,一个是非聚集索引扫描。 聚集索引扫描:聚集索引的数据体积实际是就是表本身,也就是说表有多少行多少列,聚集索引就有多 少行多少列,那么聚集索引扫描就跟表扫描差不多,也要进行全表扫描,遍历所有表数据,查找出你想 要的数据。 非聚集索引扫描:非聚集索引的体积是根据你的索引创建情况而定的,可以只包含你要查询的列。那么 进行非聚集索引扫描,便是你非聚集中包含的列的所有行进行遍历,查找出你想要的数据。

SELECT * FROM [CustomerDB].[dbo].[Product_10]

建议大家在Sql语句查询的时候,尽量不要使用* 查询;

3、Key Lookup(键值查找) 查找与扫描在性能上完全不是一个级别的,扫描需要遍历整张表,而查找只需要通过键值直接提取数 据,返回结果,性能要好。当你查找的列没有完全被非聚集索引包含,就需要使用键值查找在聚集索引 上查找非聚集索引不包含的列。

SELECT * FROM [CustomerDB].[dbo].[Product_1] where ProductNum=437703

4、RID Lookoup(RID查找) 跟键值查找类似,只不过RID查找,是需要查找的列没有完全被非聚集索引包含,而剩余的列所在的表 又不存在聚集索引,不能键值查找,只能根据行表示Rid来查询数据。

SELECT *FROM [CustomerDB].[dbo].[Product_2] where ProductNum='686440

5、Clustered Index Seek(聚集索引查找)、Index Seek(非聚集索引查找) 聚集索引查找和非聚集索引查找都是使用该图标。 聚集索引查找:聚集索引包含整个表的数据,也就是在聚集索引的数据上根据键值取数据。 非聚集索引查找:非聚集索引包含创建索引时所包含列的数据,在这些非聚集索引的数据上根据键值取 数据。

SELECT *
FROM [CustomerDB].[dbo].[Product_10] where id=19
SELECT ProductNum
FROM [CustomerDB].[dbo].[Product_4] where ProductNum<129

  6、Hash Match 一种是表关联,一种是数据聚合运算时。 再分别说这两中运算的前面,我先说说Hashing(编码技术)和Hash Table(数据结构)。 Hashing:在数据库中根据每一行的数据内容,转换成唯一符号格式,存放到临时哈希表中,当需要原 始数据时,可以给还原回来。类似加密解密技术,但是他能更有效的支持数据查询。 Hash Table:通过hashing处理,把数据以key/value的形式存储在表格中,在数据库中他被放在 tempdb中。 把关联的字段---加上索引----还建议给出查询条件,在sql语句之后,where 上条件

select * from Company c left join SysUser u on c.id=u.CompanyId

  7、Nested Loops 把两个不同列的数据集汇总到一张表中。提示信息中的Output List中有两个数据集,下面的数据集 (inner set)会一一扫描与上面的数据集(out set),扫描完为止,这个操作才算是完成。

8、Merge Join 这种关联算法是对两个已经排过序的集合进行合并。如果两个聚合是无序的则将先给集合排序再进行一 一合并,由于是排过序的集合,左右两个集合自上而下合并效率是相当快的。

select * from Product_1 c inner merge join Product_2 d on c.Id=d.Id

  

9、Sort(排序) 对数据集合进行排序,需要注意的是,有些数据集合在索引扫描后是自带排序的。

select * from Product_1 order by ProductName desc

  

10、Filter(筛选) 根据出现在having之后的操作运算符,进行筛选

SELECT COUNT(Id) idCount
FROM [CustomerDB].[dbo].[Company] group by CreateTime having COUNT(Id)=1

  

11、Computer Scalar 在需要查询的列中需要自定义列,比如count(*) as cnt ,select name+''+age 等会出现此符号。

SELECT COUNT(Id) idCount
FROM [CustomerDB].[dbo].[Company