MySQL 高级特性学习

303 阅读5分钟

前言:

目录:

一、索引(覆盖索引,索引合并,索引跳跃扫描MySQL8.0,自适应哈希索引)

二、事物

三、锁

四、性能

五、问题排查

六、高可用(了解)

七、新特性(了解)

一、索引

1.1 覆盖索引:当查询的列都包含在索引中时,mysql可以直接从索引中获取数据,避免回表操作,提高查询效率。

CREATE INDEX idx_user_email ON users(email);
SELECT email FROM users WHERE email LIKE '%@example.com%';

1.2 索引合并:mysql可以同时使用多个单列索引,并将他们的结果合并,以满足负载的查询条件。

CREATE INDEX idx_age ON users(age);
CREATE INDEX idx_city ON users(city);
SELECT * FROM users WHERE age = 30 OR city = 'New York';

1.3 索引跳跃扫描:mysql8.0引入的优化策略,允许在联合索引中跳过最左前缀,适合用于联合索引的首列基数较低的情况。

CREATE INDEX idx_a_b ON t(a, b);
SELECT * FROM t WHERE b = 100;

1.4 自适应哈希索引:InnoDB存储的引擎会自动监控访问模式,对频繁访问的B+Tree索引页建立哈希索引,以加速查询。

**使用场景**:频繁访问相同页的数据。

> 开启方式:默认启用,可通过 `innodb_adaptive_hash_index` 参数控制。

个人理解:不用刻意操作

查看当前表的索引

SHOW INDEX FROM t_sdata_plugin_property;

2 B+树索引原理与实现

B+tree是mysql默认的索引结构,具有以下特点:

  • 所有数据存储在叶子节点,非叶子节点只存储索引信息。
  • 叶子节点之间通过指针连接,支持范围查询。
  • 树的高度较低,通常为2-4层,查找效率比较高。

二、事务

明确事务的四大特性:原子性,一致性,隔离性,持久性。(ACID)

1.1 隐式提交

执行DDL或者没有显示开启事务时,自动提交事务

INSERT INTO t VALUES (1); -- 自动提交

1.2 保存点

START TRANSACTION;
INSERT INTO t VALUES (1);
SAVEPOINT sp1;
INSERT INTO t VALUES (2);
ROLLBACK TO sp1; -- 回滚第二次插入

1.3 XA分布式事务

三阶段协议

  • XA START
  • XA END / PREPARE
  • XA COMMIT / ROLLBACK

1.4 日志

  • redo log 崩溃恢复 事务执行中 性能影响小
  • binlog 主从复制 事务提交后 同步模式影响大
  • undo log 事务回滚 数据修改前 内存操作为主

三、锁

1.1 意向锁(自动) 表级锁,表示即将在行级加锁

  • 意向共享锁 (IS):表明事务打算在某些行上设置共享锁
  • 意向排他锁 (IX):表明事务打算在某些行上设置排他锁

1.2 插入意向锁(自动) 多个事务可并发插入不同区间,不互相阻塞

1.3 自增锁(自动) 对自增字段的保护,串行化写入

1.4 外键锁(自动) 在插入/更新外键时锁住父表对应行,避免约束破坏。

四、性能

1.1 子查询优化

非推荐写法:

SELECT name FROM t WHERE id IN (SELECT id FROM t2);

优化写法:

SELECT t.name FROM t JOIN t2 ON t.id = t2.id;

1.2 临时表优化

  • 避免group by/order by使用不必要的列
  • 避免使用TEXT/BLOB字段

1.3 ICP(索引条件下推)

在普通的查询过程中,即使我们使用了索引,如果where子句中有些条件不在索引上,mysql也必须先通过索引定位主键,再回表取完整行数据,再进行过滤。 而ICP会把能在索引中判断的部分条件提前在存储引擎层做判断,如果不满足就不回表直接丢弃,也就是说在回表之前就会过滤掉一部分数据,节省了大量回表的成本。

假设有表
CREATE TABLE employees (
  id INT PRIMARY KEY,
  name VARCHAR(100),
  age INT,
  department_id INT,
  INDEX idx_age_dept(age, department_id)
);

SELECT * FROM employees WHERE age > 30 AND department_id = 5;--执行

不使用ICP时:
-   MySQL 使用 `idx_age_dept` 遍历 `age > 30`;
-   然后对每一行都 **回表获取整行数据**;
-   然后在服务器层判断 `department_id = 5`。

使用ICP时:
-   MySQL 同样用 `idx_age_dept` 遍历 `age > 30`;
-   **在索引本身就能判断 `department_id = 5`**,只保留满足条件的索引条目;
-   **只有这些才回表**,极大减少 IO

判断ICP是否生效

EXPLAIN SELECT * FROM employees WHERE age > 30 AND department_id = 5;
显示:
Extra: Using index condition --生效

五、问题排查

1.1 MySQL状态排查

  • SHOW PROCESSLIST 查看慢查询/锁等待,查看当前连接、是否有阻塞

  • SHOW ENGINE INNODB STATUS 分析锁和死锁

  • SHOW GLOBAL STATUS 查看系统指标

  • SHOW VARIABLES 查看关键参数配置

  • SHOW SLAVE STATUS 查看复制延迟秒数

  • SHOW PROCESSLIST 查看是否有大事务

  • SHOW VARIABLES LIKE 'slave_parallel_workers' 是否开启并行复制

六、高可用

1.1 故障自动切换

  • 持续监控主从复制状态
  • 主库故障时自动提升最优从库为新主库
  • 自动重建复制拓扑

image.png

1.2 延迟从库

  • 防止人为误操作(提供"时间回退"能力)
  • 应对逻辑损坏(如错误的UPDATE语句)
CHANGE MASTER TO 
  MASTER_DELAY = 3600;  -- 延迟1小时
  
# 临时取消延迟(紧急恢复)
STOP SLAVE;
CHANGE MASTER TO MASTER_DELAY = 0;
START SLAVE;

1.3 多源复制

七、新特性

1.1 窗口函数 典型场景:销售排名分析

SELECT 
  product_id,
  sale_date,
  amount,
  SUM(amount) OVER (PARTITION BY product_id ORDER BY sale_date) AS running_total,
  RANK() OVER (PARTITION BY YEAR(sale_date) ORDER BY amount DESC) AS yearly_rank,
  LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date) AS prev_day_amount
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31';

1.2 JSON增强

1.3 直方图统计

1.4 CTE(通用表表达式)