-
mysql中如何定位慢查询
表象:页面加载过慢、接口压测响应时间较长(超过1秒)
可以采用开源工具如Arthas以及Skywalking,使用skywalking可以检测出哪个接口过慢。同时可以在mysql中开启慢日志查询,设置值为2秒,一旦sql执行超过2秒就记录到日志中(调试阶段)。 -
一条sql执行的很慢,应该如何分析?
可以采用EXPLAIN或者DESC命令获取MySQL如何执行select语句的信息,直接在select语句前加上expla/desc。其中的possible-key表示当前sql可能会用到的索引,key表示当前sql实际命中的索引,key-len表示索引占用的大小。extra表示额外的建议。
通过key和key-len检查是否命中了索引
通过type字段查看sql是否由进一步的优化空间,是否存在全索引扫描或全盘扫描。(index:索引树扫描/all:全盘扫描)
通过extra判断是否出现了回表的情况,如果出现了,可以尝试添加索引或者修改返回字段来修复。 -
什么是索引?
索引是MySQL中高效获取数据的数据结构(有序)主要用来提高数据检索的效率,降低数据库的IO成本同时降低数据排序的成本,也降低了CPU的消耗 -
索引的底层数据结构?
MySQL默认的存储引擎InnoDB采用的是B+树来存储索引。采用B+树的原因是:第一阶数更多,路径更短,第二个磁盘读写代价更低,非叶子节点只存储指针,叶子节点存储数据。第三是B+树便于扫库和区间查询,因为它的叶子节点是双向链表。 -
B树和B+树什么区别?
第一:B树中,非叶子节点和叶子节点都放数据,而B+树只在叶子节点存放数据,查询时,B+树效率更加稳定
第二:在进行范围查询时,B+树效率更高,因为B+树都在叶子节点存储,并且叶子节点是双向链表。 -
什么是聚簇索引?什么是非聚簇索引?
聚簇索引是指将数据存储与索引放到了一块,索引结构的叶子节点保存了一整行的数据(必须有且只有一个)
非聚簇索引(二级索引)是将数据和索引分开存储,索引结构的叶子节点关联的是对应数据的主键(可以存在多个)
一般我们自己定义的都是非聚簇索引 -
什么是回表查询?
回表的意思就是通过二级索引(非聚簇索引)找到对应的主键值,然后再通过主键值找到聚簇索引中对应的整行数据 -
什么是覆盖索引?
覆盖索引是指查询使用了索引,并且需要返回的列,在该索引中已经全部被找到。就是通过聚簇索引或者非聚簇索引一次直接命中查询的数据,没有触发回表查询。所以我们要尽量避免使用select*,尽量在返回的列中都包含添加索引的字段。 -
MySQL中超大分页怎么处理?
超大分页一般都是在数据量比较大的时候,我们使用limit进行分页查询,并且需要对数据进行排序,这个时候效率就很低。可以使用覆盖索引来解决。通过覆盖索引+子查询。先分页查询数据的id字段,确定了id之后再通过子查询来过滤,只查询这个id列表中的数据就可以了。 -
索引创建的原则有哪些?
表中数据超过10w以上通常才会创建索引,并且添加索引的字段是查询比较频繁的字段,一般也是像作为查询条件、排序字段或分组的字段这些。
通常创建索引使用联合索引来创建,一条sql的返回值,尽量使用覆盖索引。
如果一个字段内容较长,我们会考虑使用前缀索引。但索引并不是越多越好,需要控制索引的数量,添加索引也会导致增删改查的速度变慢。 -
什么情况下索引会失效?
索引在使用的时候没有遵守最左匹配法则。(查询从索引的最左前列开始,并且不跳过索引中的列,如果违反则失效,如果跳过,则只有最左列索引生效)
模糊查询时,如果%号在前面也会导致索引失效
如果在添加索引的字段上进行了运算操作或者类型转换,索引也会失效。
字符串不加单引号,也会导致索引失效
通常情况下,想判断这条sql是否有索引失效的情况,可以使用explain执行计划来分析。 -
谈一谈你对sql优化的经验
建表的时候,使用索引、sql语句的编写、主从复制、读写分离。数据量过大的时候考虑分库分表。
建表的时候,定义字段的时候需要结合字段的内容来选择合适的类型,如果是数值,像tinyint、int、bigint这些类型,要根据实际情况选择。如果是字符串类型,也是结合存储的内容来选择char、varchar、text类型。
使用索引的时候,比如select语句一定要指明字段名称,不能直接使用select*,还要注意sql语句避免造成索引失效的写法。
如果数据库的使用场景读的操作比较多的时候,为了避免写的操作锁造成的性能影响,可以采用读写分离的架构。读写分离解决的是,数据库的写入,影响了查询的效率。 -
事务的特性是什么?
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,或者同时失败(ACID)
原子性、一致性、隔离性、持久性
-
并发事务带来哪些问题?
多个事务并发进行是经常发生的,并发也是必然的。
第一个是脏读:当一个事务正在访问数据并对数据进行了修改,而这种修改还没有提交到数据库,这时另一个事务也访问了这个数据,因为这个数据是还没有提交的数据,所以另一个事务读到的数据就是脏数据,
第二个是不可重复读:比如在一个事务内多次读同一数据,在这个事务还没有结束的时候,另一个事务也访问了这个数据,那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次督导的数据是不一样的情况,因此称为不可重复度。
第三个是幻读:它发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据。在之后的查询中,第一个事务就会发现多了一些原本不存在的记录,就像发生了幻觉一样。 -
如何解决并发事务带来的问题,MySQL的默认隔离级别是什么?
我们可以通过对事务进行隔离来解决这些问题。
MySQL中支持四种隔离级别
第一个是未提交读:它解决不了脏读、不可重复读、幻读,平常也不用
第二个是读已提交:他能解决脏读
第三个是可重复读:可以解决脏读和不可重复读,但不能解决幻读(MySQL默认)
第四个是串行化:都可以解决,但性能太低。
一般都是使用可重复读(MySQL的默认隔离级别) -
undo log和redo log的区别?
redo log日志记录的是数据页的物理变化,服务宕机可以用来同步数据
undo log日志主要记录的是逻辑日志,当事务回滚时,通过逆操作恢复原来的数据
redo log保证了事务的持久性
undo log保证了事务的原子性和一致性 -
事务中的隔离性是如何保证的?
通过锁和mvcc来实现的。mvcc就是多版本并发控制,指维护一个数据的多个版本,使得读写操作没有冲突,底层实现主要分三个部分,第一个是隐藏字段,第二个是undo log日志,第三个是readView读视图。
隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事
务id),记录每一次操作的事务id,是自增的;另一个字段是roll_pointer(回
滚指针),指向上一个版本的事务版本记录地址。
undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个
版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本,
通过roll_pointer指针形成一个链表。
readView解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规
则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读
是不一样的,最终的访问的结果不一样。如果是rc隔离级别,每一次执行快
照读时生成ReadView,如果是rr隔离级别仅在事务中第一次执行快照读时生
成ReadView,后续复用