1、有哪些常见索引
唯一索引,主键索引,非空索引,组合索引,覆盖索引
2、索引失效的情况
1.以%开头的模糊查询
2.or连接,or前后的查询条件有不走索引的情况
3.where中索引列有运算或者函数
4.使用组合索引时没有遵循最左前缀匹配原则
5.数据库判断全表扫描比走索引效率更高
3、索引建立的原则(注意事项)
1.要针对where 或 on 后面的语句创建索引,而不是select后面的语句创建索引
2.频繁更新的字段不要创建索引
3.索引应该建立在小字段上面,大字段甚至超长字段,不要建立索引
4.主键,外键要有索引,经常与其他表进行连接的字段要加索引
5.经常排序,分组,去重的字段加入索引
6.更新频繁的字段,重复度高的字段,不适合加索引
4、索引的底层实现
5、MySQL 单表上亿,怎么优化分页查询?
1、表容量的问题
首先,MySQL 不管怎么优化也是很难支持单表一亿数据量带查询条件的分页查询,需要提前考虑分表分库。单表设计以 200-500 万为宜;优化的好,单表数据到一两千万,性能也还行。出现那么单表那么大的数据量,已经是设计问题了。
2、总页数的问题
页面不需要显示总页数,仅显示附近的页码,这样可以避免单表总行数的查询。
需要显示总页数,这种情况就比较难处理一些。首先 MySQL 的 MyISAM 引擎把一个表的总行数记录在磁盘中,查询 count(*) 可以直接返回;InnoDB 引擎是一行行读出来累加计数,大数据量时性能堪忧,大几秒甚至几十秒都有可能(我相信你一定遇到过)。所以 MyISAM 的总行数查询速度是比 InnoDB 快的,但这个快也仅限于不带 where 条件的。MyISAM 还有一个硬伤,不支持事务。
如何既支持事务又快速的查出总数呢?
使用 InnoDB 引擎,新建一张表记录业务表的总数,新增、删除各自在同一事务中增减总行数然后查询,保证事务的一致性和隔离性。当然,这里更新总行数要借助分布式锁或 CAS 方式更新记录总数的表。
3、具体的 SQL 优化
新增表记录业务表的总数,也是无法彻底解决带查询条件的总行数查询慢的问题。这里只能借助具体的 SQL 优化。
4、其他解法
-
继续优化数据库配置
-
提升数据库服务器硬件性能
-
引入大数据组件
-
引入大型商业数据库或者非关系型数据库解决大表问题
PS:
MySQL 大表分页问题,一般效果比较好的是,使用记录页面最大最小 ID 或统计表优化 count 查询。
从面试回答问题的角度看,如果能结合索引的实现,比如 InnoDB 的索引使用 B+ 树,子查询中索引如何生效与失效,说清楚问题的本质是就是用空间去换取查询时间,把问题提高到计算机原理(I/O、CPU 之间的权衡)、数据结构与算法的层面去阐述,肯定会加分不少。
6、慢SQL优化
- 通过慢查询日志去寻找哪些 SQL 执行效率低
- 使用 explain 获取低效率 SQL 的执行计划
- 结合 SQL 与执行计划,进行分析与优化
1.没有建索引,根据前面建索引原则建索引
2.建了索引但是索引失效了,按照前面索引失效的情况进行分析
3.单表数据量太大。解决办法:
- 分页查询(在索引上完成排序分页操作、借助主键进行关联)
- 单表数据过大,进行分库分表
- 考虑使用非关系型数据库提高查询效率
- 全文索引场景较多,考虑使用 ElasticSearch
7、索引底层实现
常用B(B-)树或B+树
首先,他们的区别是,B树每个节点不仅存储索引,也存储数据,B+树是B树的一个变种,B+树只有叶子结点存储数据,其他节点存储索引,叶子结点之间也存在链表将其关联(MySQL优化为双向链表),减少树高,减少IO,查询效率稳定,更有利于范围查询。
8、什么是存储过程
- 存储过程(Stored Procedure)是数据库中一种存储复杂程序,供外部程序调用的一种数据库对象,里面存储一段SQL语句集,可以加入业务逻辑和流程,被编译保存在数据库里面,简化复杂的操作。