优化
MySQL中,如何定位慢查询?
- 使用慢查询日志:可以在MySql配置文件当中slow_query_log来启动慢查询日志,通过定义慢查询的阈值,在慢查询日志当中记录查询时间超过阈值的SQL
如果一个SQL语句执行很慢,如何分析原因呢?
可以采用MySQL自带的分析工具Explain
- 通过key和key_len检查是否命中了索引
- 通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
- 通过extra建议判断,是否出现了回表的情况
什么是索引?
- 索引是数据库中用于加快数据检索速度的一种数据结构。它类似于书籍的目录,可以帮助数据库系统快速定位到需要查询的数据位置。
索引的底层数据结构了解过嘛 ?
- MySQL默认的存储引擎InnoDB采用的是B+树的数据结构来存储索引。选B+树原因如下
- 磁盘读取效率更高
- 查询效率更稳定
- 便于扫库和区间查询
B树和B+树的区别是什么呢?
- B树中,非叶子节点和叶子节点都会存储数据。在B+树中所有数据都会存储在叶子节点
- 在进行范围查询时,B+树效率更高。
什么是聚簇索引什么是非聚簇索引 ?
- 聚簇索引直接将索引和数据存储在一起的。一个表只能有一个聚簇索引,通常用主键来作为聚簇索引
- 非聚簇索引是将索引和数据分开存储的。其叶子结点保存了对应的主键,可以有多个非聚簇索引
什么是回表查询?
- 回表查询是通过二级索引(非聚簇索引)找到对应的主键值,然后根据主键值找到聚簇索引中该主键对应的整行数据
知道什么叫覆盖索引嘛 ?
- 是指查询使用了索引,并且查询返回的列在索引当中已经全部找到
- 如果我们使用id查询,会进行聚集索引查询效率较高
- 如果使用二级索引,如果返回的列中没有创建索引,有可能会触发回表查询,这时候查询效率就会低
MYSQL超大分页怎么处理 ?
- 超大分页是指在数据量比较大时,使用limit分页查询,需要对数据进行排序,效率低
- 覆盖索引+子查询。先分页查询符合条件数据的id字段,后再用子查询过滤(查询id时是覆盖索引,效率提升大)
索引创建原则有哪些?
- 数据量比较大,且查询比较频繁的表
- 对一些常作为查询条件、排序、分组的字段建立索引
- 对索引的数量要进行控制,因为添加索引会导致新增改的速度变慢
什么情况下索引会失效?
- 在索引列上执行字符串的模糊搜索
- 如果数据表中数据量非常的效,索引对其查询性能提高非常有限,数据库可能会选择全盘扫描
- 在索引列上应用了函数、表达式
sql的优化的经验?
我们可以从建表、索引、sql语句、主从复制、读写分离、分库分表来考虑对sql进行优化
建表:
- 选择合适的数据类型。例如用int代替varchar来存储数字ID
- 设计良好的主键
- 尽量设置默认值:可以减少插入的工作量
索引:
- 对数据量比较大、且频繁查询的表建立索引
- 对常作为查询条件、排序、分组的字段建立索引
- 对索引的数量进行控制,因为添加索引会导致新增改的速度变慢
sql语句:
- 避免使用sql*
- 如果是表的关联,尽量使用innerjoin(返回共有行)来代替leftjoin(左表所有行和右表满足条件的行)和rightjoin(右表所有行和左表满足条件的行)
- 避免在where子句中对字段进行表达式操作
主从复制、读写分离:
- 如果数据库读的操作较多写的操作较少。可以将读操作分发到从库(多个),写操作分发到主库,这样可以减轻主库的压力
其他面试题
事务是什么?有什么特性?
事务是有一组数据库操作组成,这些操作要么全部完成,要么全部失败。其具有以下特性
- 原子性:事务是原子的,它要么全部执行,要么全部不执行
- 一致性:l事务完成时,必须使所有的数据都保持一致状态。
- 隔离性:事务执行不受其他事务的干扰
- 持久性:一旦事务提交完成,将永久保存在数据库中
并发事务会带来哪些问题?
- 脏读:一个事务读取到另一个事务还没有提交的数据
- 不可重复读:一个事务中,同一查询多次执行返回的结果不同,因为其他事务在查询之间修改了数据。
- 幻读:在一个事务中执行相同的查询,但结果集不一致,因为其他事务在查询之间插入了新的数据。
怎么解决这些问题呢?MySQL的默认隔离级别是?
可以对事务进行隔离
- 未提交读(Read uncommitted):解决不了上述任何问题
- 读已提交(read committed):解决脏读
- 可重复读(Repeatable Read):脏读、不可重复读(默认)
- 串行化(serializable):解决所有问题
undo log和redo log的区别?
undo log:记录事务在执行过程中的修改操作。在提交和回滚时释放。在回滚时通过执行日志文件中的操作来进行回滚。(原子性、一致性)
redo log:记录事务提交时数据页的物理修改。防止事务提交后系统崩溃导致部分修改为写入磁盘(持久性)
事务中的隔离性是如何保证的呢?
- 排他锁:如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁
- MVCC
你解释一下MVCC?
- 是数据库管理系统中常用的并发控制机制,主要用于在多个事务同时读写数据时保证数据的一致性和事务的隔离性。
- 具体来说MVCC维护了一个数据项的多个版本,每个版本都反映了数据库在某个事务开始时的状态。当一个事务在读取数据时,MVCC会根据事务的启动时间来选择合适的版本。这样即使其他事务正在修改数据,读操作也可以继续进行,因为读取的是事务的旧版本,不受其他事务影响。
在其底层主要有三部分组成(更细的部分)
- 隐藏字段:trx_id:记录每一次操作的事务id。roll_pointer(回滚指针),指向上一个版本的事务记录地址
- undo log:主要的作用是记录回滚日志
- readView:解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据
MySQL主从同步原理?
是指将主数据库上的数据实时更新到一个或者多个从数据库上。具体步骤如下
- 主数据库修改数据时,会将修改记录写入二进制日志文件当中
- 从库获取主库的二进制日志文件,将信息写入从库的中继日志中
- 从库做中继日志中的操作,来修改自己数据
那你之前使用过分库分表吗?
- 水平分库:将一个库的数据拆分到多个库中
- 水平分表:将一个表的数据拆分到多个表中(可以在同一个库内)。
- 垂直分库:以表为依据,根据业务将不同表拆分到不同库当中
- 垂直分表:以字段为依据,将不常用的字段单独放一张表