聚簇的概念:
聚簇不是一种单独的索引类型,而是一种数据存储方式。具体细节依赖于其实现方式,但InnoDB的聚簇索引实际上在同一个结构中保存了b-tree索引和数据行。“聚簇”描述的是数据行和相邻的键值紧凑的存储在一起。
聚簇索引,他的数据行实际上存储在叶子页(leaf page ),一个表只能有一个聚簇索引。叶子页包含了所有的数据,但是节点页只包含索引列数据。
聚集的数据优点:
- 把有关的数据存储在一起
- 数据访问更快
- 使用索引覆盖扫描可以直接使用页节点中的主键值
聚簇索引的缺点:
- 内存数据库聚簇结构没有优势
- 插入速度严重依赖插入顺序
- 更新聚簇索引列的代价很高(会强制InnoDb将每个更新的行移到新的位置)
- 基于聚簇索引的表在插入新行时,或者主键更新导致需要移动行时,可能面临,页分裂(leaf split)问题,当行的主键值要求将一行插入到一个已满的数据页时,存储引擎会要求将该页分裂成两页来容纳该行。页分裂会导致表占用更多的磁盘。
- 聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
- 二级索引可能比想象的更大
- 二级索引检索需要两次索引查找(二级索引的叶子节点不是保存行的位置指针,而是保存的主键值。)
以上所有,摘自《高性能mysql》看博客的成长真的是有限的,各位,深入理解还是去啃一下原版文档和那本大砖头
5.索引覆盖、最左前缀、索引下推
10.普通索引和唯一索引的区别
查找过程:普通索引,二分查找到第一个满足条件的记录会顺序查找下一个记录,直到碰到第一个不满足条件的记录。(InnoDB数据页默认大小16k,顺序寻址代价几乎可以忽略)
唯一索引,由于具有唯一性,直接命中。
更新过程:当需要更新一个数据页时,在不影响数据一致性的前提下,InnoDB会将这些更新缓存到change buffer(持久化数据)中,这样就不需要从磁盘中读取这个数据页了。下次范围这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个数据页有关的操作。通过这个逻辑来保证数据逻辑的正确性。将change buffer中的操作应用到原数据页的过程称为merge。除了访问这个数据页会触发merge外,系统有后台线程定期merge。在数据库正常关闭的过程中,也会执行。显然将数据更新先记录到change buffer ,减少磁盘读取,语句的执行速度回明显提升。而且,读入内存需要占用buffer pool的,所以这种方式还能够避免占用内存,提高内存利用率。
对于唯一索引来说,所有更新操作都需要判断是否违反唯一性约束。这个操作必须将数据页读到内存中。如果已经读入内存了,不如直接更新内存更快,没有必要使用change buffer了。因此唯一索引不能使用change buffer因此也只有普通索引能使用。change buffer是占用buffer pool的控件,可以动态配置,最多占用50%。将数据从磁盘读入内存涉及随机IO的访问,是数据库里面成本最高的操作之一。change buffer因为减少了随机磁盘访问,所以更新性能提升会很明显。(对于写多读少的场景,页面写完后马上被方位的概率很低的情况如账单类、日志类)
12.mysql索引的选择(server层优化器的逻辑)
12.1 扫描行数 mysql在真正执行语句之前,并不能精确的知道满足这个条件的记录有多少,而只能根据统计信息估算记录数。这个统计信息就是索引的“区分度”。显然一个索引上不同的值越多,索引的区分度就越好。一个索引上不同值的数量,称之为“基数”(cardinality)。可以通过show index 查看
mysql采用采样统计的方式获取统计信息:InnoDB会默认选择N个数据页,统计这些数据页上的不同值,得到一个平均值,然后乘以这个索引的页面数量,最后得到这个索引的基数。当数据持续变化的数据行数超过M分之一的时候会自动触发重新做一次统计。
以上计算的偏差,优化器在计算代价的时候会计算普通索引需要回标的代价。
13.怎样给字符字段加索引
使用前缀索引定义好长度,既可以节省空间,又不用额外增加太多的查询成本。但是前缀索引无法使用索引覆盖。
select count(distinct email) as L from table;
select count(distinct left(email,5)) as L5 from table;
对于前缀区分度不高的场景(例如身份证号)有以下几种方式:1.倒序索引(reverse()) 2.使用hash字段(crc32())
网友评论