04 | 深入浅出索引(上)
04 | 深入浅出索引(上)
讲述:林晓斌
时长15:29大小7.10M
索引的常见模型
InnoDB 的索引模型
索引维护
小结
上期问题时间
赞 371
提建议
精选留言(617)
- JackPn置顶2018-11-27老师我可不可以理解为:每一张表其实就是一个B+树,树结点的key值就是某一行的主键,value是该行的其他数据。新建索引就是新增一个B+树,查询不走索引就是遍历主B+树。
作者回复: 每一个表是好几棵B+树(应该是你理解对了但是手误), 其它的完全正确
共 33 条评论302 - wuxue_123置顶2018-12-20老师,回表只是普通索引才会有的吗?主键和数据放在同一个树中,根据主键查询的时候,就可以直接获得数据了。 那select *from table where id=xx 和select id from table where id=xx 的效率是一样的吗?(id是主键)
作者回复: 这两个语句是都不用回表了,在“查找行”这个逻辑上是一样的, 但是select *要读和拷贝更多列到server,还要发送更多列给客户端,所以还是select id更快的。 好问题
共 29 条评论226 - Christain置顶2018-11-23老师,索引篇结束了么? 有几个问题 1 :三个字段联合索引时,如果中间的字段使用了范围查询或者模糊查询,最后一个字段还会用到索引么? 2:在order by时,索引是如何使用的 3:新建一张表,如何界定其索引的数量,有没有选择或者公式 4:能不能再详细介绍下字符串前缀索引展开
作者回复: 理论篇的先到这里,实践篇的还有六篇索引相关。 1. 我们文中有这样的例子了哦。like “张%” 就是对name 字段的范围查询/模糊查询。 age 就是你说的最后一个字段啦 😄 2. 我们有两篇的篇幅来讲order by, 第14和16(15是答疑) 3. 根据查询需要😓 4. 等《如何给字符串字段加索引》发布哈 嗯索引的内容其实很多,基础篇两篇是不可能写完的,而且怕理论类太多大家读着累,把一些知识点放到实践篇了 @all
共 7 条评论98 - 壹笙☞漂泊2018-11-21总结: 1.索引的作用:提高数据查询效率 2.常见索引模型:哈希表、有序数组、搜索树 3.哈希表:键 - 值(key - value)。 4.哈希思路:把值放在数组里,用一个哈希函数把key换算成一个确定的位置,然后把value放在数组的这个位置 5.哈希冲突的处理办法:链表 6.哈希表适用场景:只有等值查询的场景 7.有序数组:按顺序存储。查询用二分法就可以快速查询,时间复杂度是:O(log(N)) 8.有序数组查询效率高,更新效率低 9.有序数组的适用场景:静态存储引擎。 10.二叉搜索树:每个节点的左儿子小于父节点,父节点又小于右儿子 11.二叉搜索树:查询时间复杂度O(log(N)),更新时间复杂度O(log(N)) 12.数据库存储大多不适用二叉树,因为树高过高,会适用N叉树 13.InnoDB中的索引模型:B+Tree 14.索引类型:主键索引、非主键索引 主键索引的叶子节点存的是整行的数据(聚簇索引),非主键索引的叶子节点内容是主键的值(二级索引) 15.主键索引和普通索引的区别:主键索引只要搜索ID这个B+Tree即可拿到数据。普通索引先搜索索引拿到主键值,再到主键索引树搜索一次(回表) 16.一个数据页满了,按照B+Tree算法,新增加一个数据页,叫做页分裂,会导致性能下降。空间利用率降低大概50%。当相邻的两个数据页利用率很低的时候会做数据页合并,合并的过程是分裂过程的逆过程。 17.从性能和存储空间方面考量,自增主键往往是更合理的选择。 思考题: 如果删除,新建主键索引,会同时去修改普通索引对应的主键索引,性能消耗比较大。 删除重建普通索引貌似影响不大,不过要注意在业务低谷期操作,避免影响业务。展开
作者回复: 优秀
共 23 条评论802 - 约书亚2018-11-21“N叉树”的N值在MySQL中是可以被人工调整的么?曾经面试被问到过这问题,当时就懵逼了...
作者回复: 面试中题面越简单的问题越暗藏凶险,可见一斑… 可以按照调整key的大小的思路来说; 如果你能指出来5.6以后可以通过page大小来间接控制应该能加分吧 面试回答不能太精减,计算方法、前缀索引什么的一起上😄
共 70 条评论325 - 堵车2018-11-21请问没有主键的表,有一个普通索引。怎么回表?
作者回复: 没有主键的表,innodb会给默认创建一个Rowid做主键
共 6 条评论273 - 天天向上2019-03-23去面试,遇到面试官问我innodb B+树主键索引的叶子节点存的是什么,我说是行,面试官说错,存的是页, 老师讲的就是行啊,我……
作者回复: B+树的叶子节点是page (页),一个页里面可以存多个行
共 65 条评论230 - 张良2018-11-21结合王争的数据结构与算法看正好共 9 条评论190
- 张先先森森森2018-11-21drop主键索引会导致其他索引失效,但drop普通索引不会。共 8 条评论152
- 扬~2018-12-19但现在一般自增索引都设置为bigint,这点老师这么看
作者回复: 特别合理,因为现在很多业务插入数据很凶残,容易超过int 上限, 实际上是建议设置bigint unsigned 好问题
共 7 条评论130 - Richie2018-11-21老师索引只能定位到page,page内部怎么去定位行数据
作者回复: 内部有个有序数组,二分法
共 11 条评论123 - 橡皮泥boy2018-11-22【回答问题】 1. 直接删掉主键索引是不好的,它会使得所有的二级索引都失效,并且会用ROWID来作主键索引; 2. 看到mysql官方文档写了三种措施,第一个是整个数据库迁移,先dump出来再重建表(这个一般只适合离线的业务来做);第二个是用空的alter操作,比如ALTER TABLE t1 ENGINE = InnoDB;这样子就会原地重建表结构(真的吗?);第三个是用repaire table,不过这个是由存储引擎决定支不支持的(innodb就不行)。展开
作者回复: 准确
共 12 条评论103 - 路过2018-11-21顺序应是先删除k列索引,主键索引。然后再创建主键索引和k列索引。共 1 条评论86
- 高枕2018-11-21我来回答这个问题 你可以想象一下一棵 100 万节点的平衡二叉树,树高 20。一次查询可能需要访问 20 个数据块。 这里有点不理解,为什么树高20就是20个数据块? 每个叶子结点就是一个块,每个块包含两个数据,块之间通过链式方式链接。树高20的话,就要遍历20个块展开
作者回复: 👍🏿,多谢 多补一句,因为是二叉树结构,每次指针查找很大概率是触发随机磁盘读(比如很难刚好碰上一个节点和他的左右儿子刚好相邻)
共 15 条评论80 - Richie2018-11-21二级索引重建应该新建索引再做删除,如果有查询用到这个索引,此时索引已被删除,会导致业务抖动.主键重建不能采用drop这种方式去按操作,因为所有数据都是以主键组织的,删了主键后,InnoDB会自己找一个主键组织数据,再次添加主键又会重新组织数据,重建表的次已达二次,我们可以直接Optimiz这个表共 3 条评论67
- 滩涂曳尾2018-11-21老师我有2个问题,问题1是上一节遗留的没来得及问: 1. 在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。这句话能具体说明吗? 2. 访问磁盘和内存索引涉及磁盘(sata,ssd,nvm)读写性能,以及内存读写性能,可否给一些数值方便直观认识?
作者回复: 1. 就是语句开始执行前创建一个read-view 2. 我估计你要的是这个: T his group of numbers is from a presentation Jeff Dean gave at a Engineering All-Hands Meeting at Google. L1 cache reference 0.5 ns Branch mispredict 5 ns L2 cache reference 7 ns Mutex lock/unlock 100 ns Main memory reference 100 ns Compress 1K bytes with Zippy 10,000 ns Send 2K bytes over 1 Gbps network 20,000 ns Read 1 MB sequentially from memory 250,000 ns Round trip within same datacenter 500,000 ns Disk seek 10,000,000 ns Read 1 MB sequentially from network 10,000,000 ns Read 1 MB sequentially from disk 30,000,000 ns Send packet CA->Netherlands->CA 150,000,000 ns
共 3 条评论64 - 大王拍我去巡山2018-11-21老师你好:之前看过一遍文章,一直有疑惑:一个innoDB引擎的表,数据量非常大,根据二级索引搜索会比主键搜索快,文章阐述的原因是主键索引和数据行在一起,非常大搜索慢,我的疑惑是:通过普通索引找到主键ID后,同样要跑一边主键索引,还望老师解惑。。。
作者回复: 问出这个问题表示你今天的文章看明白了👍🏿 看完明天的(下),我估计你就有答案了
共 17 条评论59 - 橡皮泥boy2018-11-22【今日收获】 1. 主键索引的叶子结点存储了整一行的内容(聚簇索引),使用主键可以快速获取到整行的数据。 2. 非主键索引的叶子结点存储的是主键的值,所以主键字段占用空间不宜过大。同时,其查找数据的过程称为“回表”,需要先查找自己得到主键值,再在主键索引上边查找数据内容。 3. 索引的实现由存储引擎来决定,InnoDB使用B+树(N叉树,比如1200叉树),把整颗树的高度维持在很小的范围内,同时在内存里缓存前面若干层的节点,可以极大地降低访问磁盘的次数,提高读的效率。 4. B+树的插入可能会引起数据页的分裂,删除可能会引起数据页的合并,二者都是比较重的IO消耗,所以比较好的方式是顺序插入数据,这也是我们一般使用自增主键的原因之一。 5. 在Key-Value的场景下,只有一个索引且是唯一索引,则适合直接使用业务字段作为主键索引。展开
作者回复: 赞👍🏿
共 3 条评论51 - ☞2018-11-21老师请问下: 1、如果插入的数据是在主键树叶子结点的中间,后面的所有页如果都是满的状态,是不是会造成后面的每一页都会去进行页分裂操作,直到最后一个页申请新页移过去最后一个值 2、还有之前看到过说是插入数据如果是在某个数据满了页的首尾,为了减少数据移动和页分裂,会先去前后两个页看看是否满了,如果没满会先将数据放到前后两个页上,不知道是不是有这种情况展开
作者回复: 1. 不会不会,只会分裂它要写入的那个页面。每个页面之间是用指针串的,改指针就好了,不需要“后面的全部挪动 2. 对,减为了增加空间利用率
共 4 条评论50 - 唐堂2018-11-21@约书亚 的问题:““N叉树”的N值在Mysql是否可以被调整?” ,老师能否在稍微详细点指导下? 谢谢老师了共 2 条评论48