mysql 索引笔记 (2)

记录头信息, 顾名思义就是用来描述记录头中的信息, 记录头信息由固定的5个字节组成, 一共40位, 不同位代表的意思也不同, 如下表

名称 单位 bit 简介
预留位1   1   未使用  
预留位2   1   未使用  
delete_mark   1   标记改行记录是否被删除了  
min_rec_mark   1   标记在 B+树中每层的非叶子节点中最小的node  
n_owned   4   表示当前记录拥有的记录数  
heap_no   13   表示当前记录在堆中的位置  
record_type   3   表示当前记录的类型 , 0表示普通记录, 1表示B+树中非叶子节点记录, 2表示最小记录 ,3表示最大记录  
next_record   16   表示下一条记录的相对位置  

点击查看 参考博文2

行溢出

在mysql中每一行, 能存储的最大的字节数是65535个字节数, 此时我们使用下面的sql执行时就会出现行溢出现象

CREATE TABLE test ( c VARCHAR(65535) ) CHARSET=ascii ROW_FORMAT=Compact;

给varchar申请最大65535 , 再加上compact行格式中还有前面三个非数据列占用内存,所以一准溢出, 如果不想溢出, 可以适当的将 65535 - 3

页溢出

前面说了, InnoDB中数据的读取按照页为单位, 每一页的大小是 16kb, 换算成字节就是16384个字节, 但是每行最多存储 65535个字节啊, 也就是说一行数据可能需要好几个页来存储

怎么办呢?

compact行格式会在存储真实数据的列中多存储一部分数据, 这部分数据中存储的就是下一页的地址

dynamic行格式 中直接存储数据所在的地址, 换句话说就是数据都被存储在了其他页上

compressed行格式会使用压缩算法对行格式进行压缩处理

一般我们都是将表中的id列设置为主键, 这就会形成主键索引, 于是我们需要注意了:

主键的占用的空间越小,整体的检索效率就会越高

为什么这么说呢? 这就可以结合页的概念来解析, 在B+树这种数据结果中, 叶子节点中用来存储数据, 存储数据的格式类似Key-value key就是索引值, value就是数据内容, 如果索引占用的空间太大的话, 单页16kb能存储的索引就越小, 这就导致数据被分散在更多的页上, 致使查询的效率降低

建立索引的技巧

为某一列建立索引

给text表中的title列创建索引, 索引名字 my_index alter table text add index my_index (title);

虽然建立索引能提升查询的效率, 根据前人的经验看, 这并不是一定的, 建立索引本身会直接消耗内存空间, 同时索, 插入,删除, 这种写操作就会打破B+树的平衡面临索引的重建, 一般出现如下两种情况时,是不推荐建立索引的

表中的数据本身就很少

我们计算一下索引的选择性很低

兼顾 - 索引的选择性与前缀索引

所谓选择性,其实就是说不重复出现的索引值(基数,Cardinality) 与 表中的记录数的比值

即: 选择性= 基数 / 记录数

选择性的取值范围在(0,1]之间, 选择性越接近1 , 说明建立索引的必要性就越强, 比如对sex列进行建立索引,这里面非男即女, 如果对它建立索引的话, 其实是没意义的, 还不如直接进行全表扫描来的快

如何使用sql计算选择性呢? 严格遵循上面的公式

SELECT count(DISTINCT(title))/count(*) AS Selectivity FROM employees.titles; count(基数/记录数) DISTINCT(title) / /count(*)

更详细的例子看下面的连接

参考博文

索引失效问题

注意事项

索引无法存储null值

如果条件中有or, 即使条件中存在索引也不会使用索引,如果既想使用or,又想使用索引, 就给所有or条件控制的列加上索引

使用like查询时, 如果以%开头,肯定是进行全表扫描

使用like查询时, 如果%在条件后面

对于主键索引, 索引失效

对于普通索引, 索引不失效

如果列的类型是字符串类型, 那么一定要在条件中将数据用引号引起来,不然也会是索引失效

如果mysql认为全表扫描比用索引块, 同样不会使用索引

联合索引 什么是联合索引

联合索引, 也叫复合索引,说白了就是多个字段一起组合成一个索引

像下面这样使用 id + title 组合在一起构成一个联合索引

CREATE TABLE `text` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `content` text NOT NULL, PRIMARY KEY (`id`,`title`) ) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8

如果我们像上图那样创建了索引,我们只要保证我们的 id+title 两者结合起来全局唯一就ok

建立联合索引同样是需要进行排序的,排序的规则就是按照联合索引所有列组成的字符串的之间的先后顺序进行排序, 如a比b优先

左前原则

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfdwz.html