前言1:我会结合mysql和mssql来写。虽然是不同的数据库,但是二者索引的本质是一样的。
前言2:业务系统大多数时间无非动态条件+排序+查找,如何提升排序查找效率乃重中之重
前言3:程序猿的救命稻草——创建索引
如果你对前言的内容感兴趣(怎么会有兴趣呢,很痛苦好吧。。。)不过为了将来
升职加薪,当上总经理,赢取白富美,走上人生巅峰
请继续往下看吧
一 索引的概念
1 索引的定义
不需要太多术语,就一句话:快速查找&有序 的数据结构
堆表不保证有序
2 聚集索引和非聚集索引
聚集索引Clustered Index
1 列可以有重复值。
2如果主键默认做聚集索引,则符合唯一约束.
3索引组织表是有序的,堆表是无序的。
4只能有一个
5mysql的表就是一张索引组织表,若无主键,InnoDB engine会自动创建一个6字节(48bit)列作为主键。mssql则不会
6当select * 的时候,检索最快,因为叶子节点有全部的数据
非聚集索引NonClustered Index
1叶子节点上保存二个信息:索引字段值,对应聚集索引键值(无聚集索引,则是数据位置的指针)
2select * 浪费性能,需要标签查找。select 非聚集列 则最快
快问快答——
主键和聚集索引有什么区别?miemiemie~~
3 索引在执行计划中的术语
二索引是如何建立的---- B+树王国是如何平地而起?
1 索引是一个B+树
B+树的概念,网上一大堆,这里不赘述。我用一个图来展示B+树是如何插入元素的。
2 索引插入算法—— 灵魂画手
3 索引分页三个基本类型
聚集索引结点级(非leaf),聚集索引叶级别(就是数据行),非聚集索引结点级,非聚集索引的叶级别。
下一个章节会对索引分页详细说明,其中聚集索引叶级别,非聚集索引结点级不做细节介绍。
三 索引的内部存储
为了了解数据内部存储,我们需要先知道已下几个知识点:
1 Sqlserver 一个分页是8k,mysql一个分页则是16k。存储理论是一致的。
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