1、SQL查询每个部门工资最高的员工表结构employee(emp_id, name, salary, dept_id)department(dept_id, dept_name)方式1子查询思路先查每个部门最高薪资再关联匹配员工SELECTe.dept_id,e.name,e.salaryFROMemployee eWHERE(dept_id,salary)IN(SELECTdept_id,MAX(salary)ASsalaryFROMemployeeGROUPBYdept_id);注意一个部门可能多个员工并列最高工资该SQL可以全部查出。方式2窗口函数 RANK()SELECTdept_id,name,salaryFROM(SELECTdept_id,name,salary,RANK()OVER(PARTITIONBYdept_idORDERBYsalaryDESC)ASrnFROMemployee)tWHEREt.rn1;RANK()并列第一下一个序号会跳号DENSE_RANK()并列第一序号连续ROW_NUMBER()强行生成唯一序号只会取1个人不适合工资并列场景。2、MySQL索引原理为什么B树聚簇索引、非聚簇索引索引原理InnoDB索引存储在B树把索引键排序存到B树减少磁盘IO索引加快查询会降低写入性能插入更新需要维护树。为什么选用B树不用B树、二叉树磁盘IO特性磁盘按页读取尽量减少树的高度减少IO次数B树多路平衡树矮B树所有数据都在叶子节点非叶子只存索引键一页可以存更多索引扇出大叶子节点用链表串联范围查询、order by非常友好B树非叶子节点也存数据一页存放索引数量少树更高二叉树深度大IO次数多。聚簇索引 vs 非聚簇索引InnoDB聚簇索引主键就是聚簇索引叶子节点存放完整行数据一张表只有1个聚簇索引数据本身按照主键顺序存放在叶子。非聚簇索引二级索引普通索引、唯一索引叶子节点存主键值不是整行数据查询普通索引查到主键再回表去聚簇索引拿完整行数据。MyISAM全部是非聚簇索引索引和数据分开文件存储。3、事务ACID4种隔离级别脏读、不可重复读、幻读ACIDA 原子性 Atomicity事务全部成功或者全部失败回滚。C 一致性 Consistency事务前后数据约束不变由原子、隔离、持久共同保证。I 隔离性 Isolation多个事务之间互相隔离。D 持久性 Durability事务提交后修改永久保存宕机不丢失。4个隔离级别从低到高读未提交 Read Uncommitted允许读取未提交数据会出现脏读、不可重复读、幻读。读已提交 Read Committed(RC)只能读到已经提交的数据解决脏读存在不可重复读、幻读MySQL快照读基于当前读。可重复读 Repeatable‑Read(RR) MySQL默认同一个事务多次读取结果一致解决脏读、不可重复读存在幻读InnoDB靠MVCC快照实现。串行化 Serializable最高级别全部加锁完全隔离全部问题解决性能差。现象定义脏读读到其他事务未提交的数据如果对方回滚读到脏无效数据。不可重复读同一个事务内同一行数据两次读取结果不一样中间被别的事务update提交。幻读同一个事务同样查询条件前后返回行数不一样别的事务insert/delete提交。InnoDB RR级别通过MVCC解决快照读幻读当前读select … for update仍会幻读靠临键锁解决。4、MySQL慢查询分析explain关键字段慢查询分析步骤开启慢查询日志设置long_query_time阈值记录执行超过阈值SQL使用mysqldumpslow工具分析慢日志拿到慢SQL执行explain看执行计划分析索引、扫描行数、type优化SQL、增加索引、改写业务逻辑。explain重点字段id执行顺序id大优先执行id相同从上往下。select_typeSIMPLE简单查询PRIMARY主查询SUBQUERY子查询DERIVED派生表。type访问类型性能从优到劣system const eq_ref ref range index ALL尽量避免ALL全表扫描。key实际用到的索引null代表没有使用索引。key_len索引使用字节长度可以判断联合索引用到几列。rows预估扫描行数数值越大越差。Extra额外信息Using index覆盖索引很好Using where存储引擎返回后再过滤Using filesort文件排序没有用到索引排序需要优化Using temporary使用临时表group by/union场景性能差。5、Redis常用数据类型以及适用场景String 字符串K‑V缓存、计数器、分布式锁、session。List 列表双向链表消息队列、栈、最新消息列表。Hash 哈希对象存储存储用户、商品对象属性。Set 集合无序不重复去重、交集并集差集、抽奖。ZSet 有序集合带score排序排行榜、延时队列。高级类型Bitmaps位运算活跃用户统计HyperLogLog海量数据去重统计允许误差Geo地理位置Stream消息队列。6、缓存穿透、缓存击穿、缓存雪崩以及解决方案缓存穿透查询不存在的数据缓存和数据库都没有请求直接打到数据库。解决参数校验过滤非法ID缓存空值布隆过滤器把合法key放布隆非法直接拦截。缓存击穿热点key过期大量并发同时打向数据库。解决热点key永不过期互斥锁分布式锁只放一个请求去更新缓存。缓存雪崩大量缓存key同时失效或者Redis宕机大量请求全部压数据库。解决过期时间加随机偏移避免同时过期Redis集群高可用服务限流熔断降级多级缓存。7、RDB与AOF持久化区别优缺点Redis持久化防止宕机内存数据丢失。RDBAOF快照某个时间点完整内存镜像记录每一条写命令日志二进制文件体积小命令日志体积更大fork子进程生成dump.rdb主线程追加写aof文件恢复速度快恢复慢重放全部命令会丢失两次快照之间的数据丢失最后一秒数据配置可调整RDB优点文件小恢复快适合备份缺点有丢失数据风险fork有开销。AOF优点数据更安全缺点文件大恢复慢可以AOF重写压缩日志。生产一般RDBAOF同时开启。8、消息队列如何保证消息不丢失幂等消费消息丢失分3个环节生产者、MQ服务端、消费者。保证消息不丢失生产者不丢开启confirm确认机制发送失败重试记录日志。MQ服务端不丢消息持久化集群副本不开启自动删除。消费者不丢关闭自动ACK业务处理完成后手动ACK处理失败不要ack。幂等消费重复消费处理MQ可能重复投递业务必须幂等。方案每条消息携带唯一业务ID消费前查询数据库是否已经处理过数据库唯一约束业务状态机判断Redis记录已消费id。9、索引失效常见场景like %xxx前缀模糊查询like xxx%可以走索引。在索引列做函数运算、隐式类型转换where cast(col as ...)、字符串和数字对比。or条件其中一个字段没有索引。联合索引不满足最左前缀原则。MySQL优化器判断全表扫描比索引更快放弃索引数据量小、数据倾斜。使用!、is not null不一定失效要看数据分布。字符串不加引号发生隐式转换索引失效。排序order by字段不在索引产生filesort。注意不是!一定失效要看explain执行计划不要死记硬背。