MySQL 数据操纵与数据库优化
MySQL数据库的DML
一、创建(Create)
1. 基本语法
INSERT INTO 表名 [(列名1, 列名2, ...)] 
VALUES (值1, 值2, ...);- 省略列名条件:当值的顺序与表结构完全一致时,可省略列名(需包含所有字段值)
- 批量插入:单条语句插入多行数据提升效率 INSERT INTO student (id, name, score) VALUES (1, '张三', 99), (2, '李四', 88), (3, '王五', 77);
2. 高级技巧
- 自增主键处理:使用AUTO_INCREMENT时,无需显式插入主键值
- 大数据量优化:调整max_allowed_packet参数避免数据包过大错误SET GLOBAL max_allowed_packet = 1024*1024*100; -- 扩容至100MB[1][8]
- 核心功能:max_allowed_packet定义了 MySQL 服务器和客户端之间传输的数据包最大允许大小。当执行大容量插入、更新或查询时,若数据包超过该限制,会触发PacketTooBigException错误。
- 适用场景:处理大型 BLOB 字段、批量导入数据、数据迁移等需要传输大容量数据的操作。
- 临时生效:通过 SET GLOBAL修改的参数仅在当前 MySQL 服务运行期间生效,重启服务后会恢复为配置文件中的默认值。若需永久生效,需修改配置文件(如my.cnf或my.ini)并重启服务。
- 单位限制: - 在命令行中设置时,只能使用字节数(如 1024*1024*100),不可直接使用M或G单位。
- 在配置文件中则支持 M/G单位(如max_allowed_packet=100M)。
 
- 在命令行中设置时,只能使用字节数(如 
- 取值范围:最小值为 1KB,最大值为1GB(超过会自动调整为1GB)。
二、读取(Retrieve)
1. 基础查询
- 全列查询:SELECT * FROM 表名(需警惕性能问题,建议指定必要字段)
- 别名设置:增强结果可读性 SELECT name AS 学生姓名, age+5 AS 修正年龄 FROM student;
2. 聚合函数与分组
- 核心聚合函数: SELECT COUNT(*) AS 总人数, AVG(score) AS 平均分,MAX(score) AS 最高分 FROM exam_result;- COUNT统计行数时推荐使用- COUNT(*),避免NULL值干扰
 
- 分组查询: 
 与WHERE区别:WHERE在分组前过滤,HAVING在分组后过滤SELECT course_id, AVG(grade) FROM study GROUP BY course_id HAVING AVG(grade) > 80; -- HAVING对分组后数据筛选[4][5]
3. 子查询
- WHERE子句嵌套: SELECT name FROM student WHERE id IN (SELECT student_id FROM study WHERE course_id = 'CS101' );
- FROM子句派生表: SELECT t.dept_name, avg_salary FROM (SELECT dept_id, AVG(salary) AS avg_salary FROM emp GROUP BY dept_id ) t;
4. 多表连接
- 内连接:仅返回匹配记录 SELECT s.name, sc.score FROM student s INNER JOIN study sc ON s.id = sc.student_id;
- 左外连接:保留左表所有记录 SELECT s.name, sc.score FROM student s LEFT JOIN study sc ON s.id = sc.student_id;
三、更新(Update)
1. 基础语法
UPDATE 表名 
SET 列名1=值1, 列名2=值2 
WHERE 条件; -- 必须指定条件避免全表更新[8][9]示例:UPDATE emp SET salary=salary*1.1 WHERE dept='研发部';
2. 级联更新
UPDATE study 
SET grade=grade+5 
WHERE course_id IN (SELECT id FROM course WHERE teacher='张教授'
);四、删除(Delete)
1. 条件删除
DELETE FROM 表名 WHERE 条件; -- 未加条件将清空全表[8]示例:DELETE FROM log WHERE create_time < '2023-01-01';
2. 高效清空(巧用DDL)
TRUNCATE TABLE student; -- 重置自增主键,性能优于DELETE[1][8]限制:外键约束存在时不可用,需先解除约束
五、约束与完整性
1. 主键与外键
CREATE TABLE student_course (student_id INT REFERENCES student(id) ON DELETE CASCADE,course_id INT REFERENCES course(id),PRIMARY KEY(student_id, course_id) -- 复合主键[1][5]
);- 级联操作:ON DELETE CASCADE实现主表删除时自动清理关联数据
2. 唯一性与默认值
CREATE TABLE user (id INT AUTO_INCREMENT PRIMARY KEY,email VARCHAR(255) UNIQUE, -- 唯一约束status TINYINT DEFAULT 1 -- 默认值约束[8][9]
);小结
MySQL CRUD操作是数据库开发的基础,掌握其正确使用规则可以提高开发效率和数据安全性。在实际应用中,需要注意以下几点:
- 避免频繁使用SELECT *,尽量指定需要的列。
- 更新和删除操作时,务必添加WHERE条件,防止误操作。
- 使用TRUNCATE时,确保表中没有外键约束。
- 合理设计表结构和约束,提高数据的完整性和一致性。
MySQL数据库优化
一、查询优化:从 SQL 到索引的全面调优
-  EXPLAIN 分析查询(查执行计划) EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';- 关键字段解读: - type:- ALL(全表扫描,需优化)→ 目标优化到- ref或- range
- key:显示实际使用的索引,若为- NULL表示未用索引
- rows:预估扫描行数,数值越大性能越差
- Extra:出现- Using filesort(额外排序)或- Using temporary(临时表)需警惕
 
 
- 关键字段解读: 
-  避免全表扫描的 3 大技巧 - 索引覆盖:确保 WHERE、JOIN、ORDER BY 涉及的列都有索引
- 函数陷阱:禁止在索引列用函数(如 YEAR(created_at)),改用范围查询-- 错误:索引失效 SELECT * FROM users WHERE YEAR(created_at) = 2023; -- 正确:索引生效 SELECT * FROM users WHERE created_at BETWEEN '2023-01-01' AND '2023-12-31';
- 模糊查询优化:避免 LIKE '%abc%',改用LIKE 'abc%'(前缀匹配可用索引)
 
-  索引优化的黄金法则 - 覆盖索引:查询字段全在索引中,无需回表 CREATE INDEX idx_email_name ON users(email, name); -- 联合索引 SELECT email, name FROM users WHERE email = 'user@example.com'; -- 直接命中索引
- 前缀索引:对长文本(如地址)截取前 20 字符建索引,节省空间  CREATE INDEX idx_title_prefix ON articles(title(20));
- 索引避坑: - 删除未使用的索引(如单字段索引被联合索引覆盖)
- 联合索引顺序遵循最左前缀原则((a,b,c)索引对a、a,b生效,对b,c无效)
 
 
- 覆盖索引:查询字段全在索引中,无需回表 
-  JOIN 与分页的高效写法 - JOIN 优化: - 用小表驱动大表(如 FROM 小表 JOIN 大表)
- 确保关联字段有索引,避免笛卡尔积
 
- 用小表驱动大表(如 
- 分页优化(百万级数据场景): -- 传统分页(慢):需扫描前 100000 行 SELECT * FROM users LIMIT 100000, 10; -- 优化方案:通过覆盖索引跳过偏移量 SELECT * FROM users WHERE id >= (SELECT id FROM users ORDER BY id LIMIT 100000, 1) ORDER BY id LIMIT 10;
 
- JOIN 优化: 
二、表结构优化:从设计到存储的进阶
-  数据类型选择 - 数值型优先:用 INT存 IP(INET_ATON()转换),而非VARCHAR
- 避免 NULL:用默认值(如空字符串)替代,减少索引复杂度
- ENUM 妙用:有限值字段(如性别)用 ENUM 比 VARCHAR 更省空间
 
- 数值型优先:用 
-  范式与反范式的平衡 - 范式化(减少冗余):适合写多读少场景(如日志表)
- 反范式化(适当冗余):读多写少场景(如用户表冗余常用字段)
 
-  分区与分库分表 - 分区表:按时间切分历史数据,加速查询 CREATE TABLE logs (id INT, log_date DATE) PARTITION BY RANGE (YEAR(log_date)) (PARTITION p2020 VALUES LESS THAN (2021),PARTITION p2023 VALUES LESS THAN (2024) );
- 分库分表:单表超千万行时用 ShardingSphere 分片
 
- 分区表:按时间切分历史数据,加速查询 
三、服务器参数调优:关键配置详解
-  InnoDB 核心参数 innodb_buffer_pool_size = 16G # 物理内存的 70%-80% innodb_file_per_table = ON # 每个表独立表空间
-  查询缓存慎用 - 适用场景:读多写极少(如静态配置表)
- 禁用场景:高并发写入时,缓存频繁失效反降低性能 query_cache_type = 0 # 高写入场景关闭
 
-  连接与内存管理 max_connections = 500 # 根据业务负载调整 wait_timeout = 600 # 空闲连接 10 分钟断开 tmp_table_size = 64M # 增大临时表内存
四、架构优化:高可用与扩展方案
- 读写分离 - 主库处理写操作,从库处理读请求(用 ProxySQL 路由)
 
- 高可用方案 - MHA:自动故障转移,主库宕机 30 秒内切换
- Galera Cluster:多主同步,适合写负载均衡场景
 
- 缓存与负载均衡 - Redis 缓存热点数据:减少数据库压力
- HAProxy:均衡读请求到多个从库
 
五、锁与事务优化:并发控制秘诀
-  隔离级别选择 - 默认 REPEATABLE READ适合多数场景
- 高并发读写可用 READ COMMITTED减少锁竞争
 
- 默认 
-  死锁监控与处理 innodb_print_all_deadlocks = 1 # 记录死锁日志- 重试机制:代码层捕获死锁异常后自动重试
 
六、监控与工具:数据库的“健康管家”
-  内置工具 - 慢查询日志:定位耗时 SQL  slow_query_log = 1 long_query_time = 2 # 记录超过 2 秒的查询
- SHOW PROCESSLIST:实时查看活跃连接
 
- 慢查询日志:定位耗时 SQL  
-  第三方利器 - Percona Toolkit:分析索引效率与表结构
- Prometheus + Grafana:可视化监控 QPS、连接数等
 
七、硬件与系统优化:底层性能基石
-  磁盘与文件系统 - SSD 替代 HDD:随机读写性能提升 10 倍+
- XFS 文件系统:禁用 atime减少磁盘写入mount -o noatime,nodiratime /dev/sdb1 /data
 
-  内核参数调优 - TCP 缓冲区:增大网络吞吐量
- 文件句柄数:避免 Too many open files错误
 
八、持续维护:数据库的“养生之道”
- 定期维护 - 每月优化碎片化表:OPTIMIZE TABLE large_table;
- 清理历史数据:分区表直接 DROP PARTITION
 
- 每月优化碎片化表:
- 避免过度优化 - 二八原则:优先优化 20% 高频查询
- 业务优先:架构扩展前评估投资回报率(如分库分表成本高)
 
优化顺序指南
- 紧急处理:慢查询优化(见效最快)
- 结构调优:索引、表设计、分区
- 参数调优:InnoDB 配置、连接数
- 架构扩展:读写分离、缓存层
- 硬件升级:SSD、内存扩容
总结
MySQL 优化是持续过程,需结合业务场景选择策略。建议从 EXPLAIN 分析和索引优化入手,逐步深入架构设计。记住:“没有银弹,只有最适合的方案!”
