索引的本质

前言1:我会结合mysql和mssql来写。虽然是不一样的数据库,可是两者索引的本质是同样的。mysql

前言2:业务系统大多数时间无非动态条件+排序+查找,如何提高排序查找效率乃重中之重算法

前言3:程序猿的救命稻草——建立索引sql

若是你对前言的内容感兴趣(怎么会有兴趣呢,很痛苦好吧。。。)不过为了未来数据库

升职加薪,当上总经理,赢取白富美,走上人生巅峰

请继续往下看吧bash

一 索引的概念

1 索引的定义数据结构

不须要太多术语,就一句话:快速查找&有序 的数据结构工具

堆表不保证有序性能

2 汇集索引和非汇集索引

汇集索引Clustered Index
1 列能够有重复值。
2若是主键默认作汇集索引,则符合惟一约束.
3索引组织表是有序的,堆表是无序的。
4只能有一个
5mysql的表就是一张索引组织表,若无主键,InnoDB engine会自动建立一个6字节(48bit)列做为主键。mssql则不会
6当select * 的时候,检索最快,由于叶子节点有所有的数据

非汇集索引NonClustered Index
1叶子节点上保存二个信息:索引字段值,对应汇集索引键值(无汇集索引,则是数据位置的指针)
2select * 浪费性能,须要标签查找。select 非汇集列 则最快复制代码

快问快答——ui

主键和汇集索引有什么区别?miemiemie~~spa

3 索引在执行计划中的术语

结构
SCAN
SEEK
堆(没有汇集索引的表格数据页)
Table Scan
没有汇集索引
汇集索引
Clustered Index Scan
有汇集索引,但也是全表扫描
Clustered index seek
用索引结果检索Data
非汇集索引
Index Scan
有非汇集索引,只是小部分Data扫描,比整表扫描代价小得多
index seek
用索引结果检索Data

二索引是如何创建的---- B+树王国是如何平地而起?

1 索引是一个B+树

B+树的概念,网上一大堆,这里不赘述。我用一个图来展现B+树是如何插入元素的。

2 索引插入算法—— 灵魂画手



3 索引分页三个基本类型

汇集索引结点级(非leaf),汇集索引叶级别(就是数据行),非汇集索引结点级,非汇集索引的叶级别。

下一个章节会对索引分页详细说明,其中汇集索引叶级别,非汇集索引结点级不作细节介绍。

三 索引的内部存储

为了了解数据内部存储,咱们须要先知道已下几个知识点:

1 Sqlserver 一个分页是8k,mysql一个分页则是16k。存储理论是一致的。

PageType(分页类型)
1:数据页面;2:索引页面;3:Lob_mixed_page;4:Lob_tree_page;10:IAM页面
IndexID (索引ID)
0 表明堆, 1 表明汇集索引, 2-250 表明非汇集索引 ,大于250就是text或image字段
sysindexes keycnt
0堆;1惟一汇集索引;2不带惟一汇集索引、惟一非汇集索引
接下来,是正餐:

A汇集索引的节点行(非leaf)

组成:索引键值+下级指针


dbcc page(test,1,162,1) --索引leafdbcc page(test,1,178,1) -- 索引节点dbcc page(test,1,898,1) --根索引复制代码

B非汇集索引的叶级行

1 非汇集索引+堆表

组成:非汇集键+ RID


2非汇集索引+汇集索引

组成:非汇集键值+汇集键值


3非汇集索引+汇集索引(字段重叠)


C非汇集索引的节点行

组成:非汇集键值+向下指针

四 没有灵丹妙药——索引的代价

1 在项目中,我见过索引列数据类型是 varchar(500)的

做为索引键值的列,数据类型太大
从上面能够得知,数据页大小是固定的.
一个索引行越长,那么一个数据页所能容纳的索引就越少,这样索引树就会复杂。
查询的时候产生的io就越多。
而数据库的查询处理器在选择执行计划的时候,若是使用索引的成本过高,那么数据库就会选择全表扫描,那么添加索引的意义在哪儿呢?复制代码

2物理表随意加索引

从问题1过渡过来,若是索引过多了,会怎样呢?
有的攻城狮真的不要太大方,索引嗷嗷的加。最后索引比真正数据文件还要大。。。
索引是落磁盘的,是增长存储压力的。索引越多统计信息就越多,写入会变慢。
那么,应该怎么加呢?
应该参考业务需求,热点表热点查询加索引,争取一个索引能够覆盖多个查询。复制代码

五经常使用索引工具

/*
* 索引实际大小
* 获得索引名字
* Jaki Wang
*/
create function fn_Index_name(@object_id int,@index_id int)
returns sysname
as 
begin
declare @index_name sysname
select @index_name = name 
from sys.indexes 
where object_id=@object_id and index_id=@index_id
return @index_name
end复制代码
相关文章
相关标签/搜索