MySQL面试01

MySQL 索引的最左原则

🍰 最左原则本质
=͟͟͞͞( •̀д•́) 想象复合索引是电话号码簿!
索引 (a,b,c) 的排列顺序:
先按a排序 → a相同按b排序 → 最后按c排序

生效场景三连:
1️⃣ WHERE a=1 ✅
2️⃣ WHERE a=1 AND b=2 ✅
3️⃣ WHERE a=1 AND b=2 AND c=3 ✅

💣 失效场景三连:
1️⃣ WHERE b=2 ❌ (跳过了a)
2️⃣ WHERE a=1 AND c=3 ❌ (中间断了b)
3️⃣ WHERE b=2 AND c=3 ❌ (首列失踪)

✨ 特殊技巧:

  • WHERE a>1 AND b=2 → 只有a能用索引(范围查询后断链)
  • WHERE a=1 ORDER BY b,c → 排序也能用索引!
  • WHERE a LIKE '张%' ✅ (前缀匹配)

哦呜(°ロ°)!曼波举个栗子:
索引是(班级, 姓名, 年龄)
✅ 查"3班 张三" → 直接翻到3班区域找张三
❌ 直接查"年龄18" → 要扫描全校学生

InnoDB 和 Mylsam 引擎的区别?

这两个引擎的区别就像奶茶和咖啡的选择,要根据场景来pick哦!

🍵 MyISAM(经典奶茶型)
=͟͟͞͞( •̀д•́) 适合读多写少的场景!

  • 不支持事务(像现金交易,要么成功要么失败)
  • 表级锁(修改时要锁整个表)
  • 存储结构:
    .MYD数据文件 + .MYI索引文件(像分开的奶茶和珍珠)
  • 特色技能:
    ✅ 全文索引
    ✅ COUNT(*) 超快(自带计数器)
    ❌ 崩溃后容易数据损坏

☕ InnoDB(现代咖啡机型)
(๑•̀ㅂ•́)و✧ 适合高并发事务场景!

  • 支持ACID事务(像电子支付可回滚)
  • 行级锁(只锁修改的行)
  • 存储结构:
    聚簇索引(数据&索引存在一起像浓缩咖啡)
  • 特色技能:
    ✅ 外键约束
    ✅ 崩溃自动恢复(redo log像咖啡机自动清洁)
    ✅ MVCC多版本并发控制

📊 性能对比小剧场:

  • 全表COUNT:MyISAM 🚀(秒出结果) vs InnoDB 🐢(要扫描)
  • 并发写入:MyISAM 😵(表锁阻塞) vs InnoDB 😎(行锁流畅)
  • 数据安全:MyISAM 🚑(需定期修复) vs InnoDB 🛡️(自动恢复)

(✪▽✪)曼波~~ 现在主流都用InnoDB啦~就像大家现在更爱喝手冲咖啡!除非特殊需求(比如全文检索),否则推荐默认选InnoDB哦!

有哪些优化数据库性能的方法?

一、💡 SQL 优化三板斧

1. EXPLAIN 大法

EXPLAIN SELECT * FROM users WHERE age > 25 ORDER BY create_time;
-- 重点观察:type(扫描类型)、key(使用索引)、rows(扫描行数)

2. 索引优化技巧

  • 给WHERE/ORDER BY/JOIN字段加索引
  • 避免在索引列上做计算:WHERE YEAR(create_time)=2023 ❌
  • 使用覆盖索引:SELECT 索引字段

3. 慢查询日志分析

# my.cnf 配置
slow_query_log = 1
long_query_time = 1  # 超过1秒的查询

mysqldumpslow工具分析日志


二、🚀 结构设计优化

1. 三范式与反范式的平衡

  • 适度冗余:减少JOIN次数
  • 大字段分离:把TEXT/BLOB单独存表

2. 分区表实战

-- 按时间范围分区
CREATE TABLE logs (
    id INT,
    log_time DATETIME
) PARTITION BY RANGE (YEAR(log_time)) (
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024)
);

3. 冷热数据分离

  • 热数据:最近3个月订单 → SSD存储
  • 冷数据:历史订单 → HDD归档

三、⚙️ 配置调优示例

InnoDB 核心参数

innodb_buffer_pool_size = 70%内存  # 缓存池大小
innodb_flush_log_at_trx_commit = 2  # 平衡安全与性能
max_connections = 1000  # 根据实际调整

四、🛠️ 架构级优化

1. 读写分离

  • 主库处理写操作
  • 从库处理读查询

2. 缓存策略

import redis.clients.jedis.Jedis;

public class UserService {
    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379;
    
    // 曼波小贴士:真实项目要用连接池哦!
    public User getUser(String userId) {
        try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT)) {
            // 1. 先查缓存
            String redisKey = "user:" + userId;
            String cachedData = jedis.get(redisKey);
            
            if (cachedData != null) {
                return JSON.parseObject(cachedData, User.class); // 使用JSON库反序列化
            }
            
            // 2. 缓存未命中则查数据库
            User user = jdbcTemplate.queryForObject(
                "SELECT * FROM users WHERE id = ?", 
                new Object[]{userId}, 
                new UserRowMapper()
            );
            
            // 3. 写入缓存(设置1小时过期)
            if (user != null) {
                jedis.setex(redisKey, 3600, JSON.toJSONString(user));
            }
            return user;
        }
    }
}

3. 分库分表

  • 垂直分库:用户库、订单库分离
  • 水平分表:user_001, user_002...


(✪▽✪)曼波~~ 记住优化要像中医把脉,先诊断(分析慢查询)再开方(针对性优化)!

如何定位慢查询?

一、🔍 基础定位三板斧

1. 慢查询日志捕获

-- 临时开启(重启失效)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- 超过1秒的查询
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- 永久生效配置(my.cnf)
[mysqld]
slow_query_log = 1
long_query_time = 1
log_queries_not_using_indexes = 1  -- 记录未走索引的查询

2. 日志分析神器

# 查看最耗时的10个慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

# 解析结果示例
Count: 5  Time=3.21s (16s)  Lock=0.00s (0s)  Rows=1000.0 (5000)
  SELECT * FROM orders WHERE user_id=N

 

3. 实时监控SHOW PROCESSLIST

-- 查看正在运行的查询
SHOW FULL PROCESSLIST;

-- 重点关注:
State: "Sending data"      -- 正在传输数据
Time: 大于100秒的查询       -- 可能卡住的查询

二、🔧 深度分析工具包

1. EXPLAIN 执行计划解读

EXPLAIN FORMAT=JSON 
SELECT * FROM products 
WHERE category='electronics' 
ORDER BY price DESC;

-- 关键指标:
"access_type": "ALL"        -- 全表扫描(危险!)
"rows_examined_per_scan": 10000  -- 扫描行数
"using_filesort": true      -- 文件排序(需优化)
 

2. Performance Schema 监控

-- 开启性能监控
UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES' 
WHERE NAME LIKE '%statement/%';

-- 查询TOP SQL
SELECT DIGEST_TEXT, AVG_TIMER_WAIT 
FROM performance_schema.events_statements_summary_by_digest 
ORDER BY AVG_TIMER_WAIT DESC 
LIMIT 10;
 

3. pt-query-digest 高级分析

# 使用Percona Toolkit
pt-query-digest /var/log/mysql/slow.log

-- 输出包括:
# Rank 响应时间占比
# Attribute 各SQL指纹
# Exec time 执行时间统计
 

三、🚀 Java生态专用方案

1. Druid 连接池监控

// Spring Boot配置
@Bean
public ServletRegistrationBean<StatViewServlet> druidServlet() {
    return new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
}

// 监控指标包括:
- SQL执行时间排行
- 慢SQL记录(支持配置阈值)
- 执行次数TOP SQL
 

2. MyBatis 打印慢SQL

<!-- mybatis-config.xml -->
<settings>
    <setting name="defaultStatementTimeout" value="5"/> <!-- 超时5秒 -->
</settings>

<!-- 配合p6spy记录真实SQL -->
driverClassName=com.p6spy.engine.spy.P6SpyDriver


 

(✪▽✪)曼波~~ 定位到慢SQL后,记得用「EXPLAIN+SQL重写+索引优化」三连击哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值