1. MySQL 常用 SQL 语句全景解析
从事数据库开发十年来,我整理过不下20个项目的SQL脚本。今天这份手册不同于官方文档的刻板罗列,而是从真实业务场景出发,将高频使用的SQL语句按操作类型分类,并附上实际项目中的优化技巧和避坑指南。
2. 基础查询语句精要
2.1 数据检索基础
-- 最基本的全表查询(生产环境慎用) SELECT * FROM employees; -- 推荐写法:明确字段+分页 SELECT emp_id, emp_name, dept FROM employees LIMIT 100 OFFSET 0;注意:阿里Java开发规范中明确要求禁止使用SELECT *,字段显示列出可减少网络传输量,当表结构变更时也能避免应用程序出错。
2.2 条件查询进阶
-- 日期范围查询(索引生效写法) SELECT * FROM orders WHERE create_time BETWEEN '2023-01-01 00:00:00' AND '2023-01-31 23:59:59'; -- NULL值处理 SELECT * FROM customers WHERE phone IS NOT NULL;实战经验:BETWEEN对日期范围查询会包含边界值,而>和<组合不会。我曾遇到过一个生产事故,统计脚本因这个差异导致少计算了临界时刻的数据。
3. 数据操作语言(DML)实战
3.1 高效插入策略
-- 批量插入(性能比单条高10倍+) INSERT INTO products (name, price) VALUES ('鼠标', 99), ('键盘', 199), ('显示器', 999); -- 带冲突处理 INSERT INTO users (user_id, username) VALUES (1, 'admin') ON DUPLICATE KEY UPDATE username = VALUES(username);批量插入时建议每批500-1000条,过大会导致事务日志膨胀。曾有个电商项目因一次性插入10万条导致数据库hang住。
3.2 更新操作要点
-- 带子查询的更新 UPDATE employee_salary es SET es.salary = es.salary * 1.1 WHERE es.dept_id IN ( SELECT dept_id FROM departments WHERE location = '上海' ); -- 使用JOIN更新(MySQL特有语法) UPDATE orders o JOIN customers c ON o.cust_id = c.cust_id SET o.discount = 0.9 WHERE c.vip_level > 3;4. 复杂查询与性能优化
4.1 多表连接实战
-- 三表关联查询(注意执行计划) SELECT o.order_no, c.cust_name, p.product_name FROM orders o INNER JOIN customers c ON o.cust_id = c.cust_id LEFT JOIN products p ON o.product_id = p.product_id WHERE o.create_time > '2023-06-01' ORDER BY o.amount DESC LIMIT 100;连接查询的黄金法则:
- 小表驱动大表
- 优先使用INNER JOIN
- 被驱动表连接字段必须有索引
4.2 子查询优化方案
-- 将IN子查询改为JOIN SELECT * FROM products WHERE category_id IN ( SELECT category_id FROM hot_categories ); -- 优化后 SELECT p.* FROM products p JOIN hot_categories hc ON p.category_id = hc.category_id;在MySQL 5.6版本中,我曾优化过一个耗时15秒的查询,通过将NOT EXISTS改为LEFT JOIN IS NULL,最终降到0.2秒。
5. 事务与锁机制深度解析
5.1 事务控制语句
-- 典型事务模板 START TRANSACTION; UPDATE account SET balance = balance - 100 WHERE user_id = 1; UPDATE account SET balance = balance + 100 WHERE user_id = 2; COMMIT; -- 异常处理 BEGIN; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SELECT 'Transaction failed' AS result; END; -- 业务SQL... COMMIT;5.2 锁等待排查案例
-- 查看当前锁等待 SELECT * FROM information_schema.INNODB_LOCK_WAITS; -- 杀死阻塞进程 KILL [process_id];去年双十一大促时,我们通过这个方式解决了因未提交事务导致的连锁阻塞,平均响应时间从5秒降到200ms。
6. 数据库对象管理
6.1 表结构修改规范
-- 添加字段(Always加注释) ALTER TABLE employees ADD COLUMN wechat VARCHAR(50) COMMENT '微信号', ADD INDEX idx_wechat (wechat); -- 大表修改方案(pt-online-schema-change) -- 1. 创建影子表 -- 2. 增量数据同步 -- 3. 原子切换6.2 索引管理最佳实践
-- 创建组合索引 ALTER TABLE orders ADD INDEX idx_composite (cust_id, status, create_time); -- 查看索引使用情况 SELECT * FROM sys.schema_index_statistics WHERE table_schema = 'your_db';索引设计的血泪教训:某交易表建立了15个单列索引,导致写入性能下降70%。后调整为3个组合索引,TPS提升3倍。
7. 高级特性应用
7.1 窗口函数实战
-- 部门薪资排名 SELECT emp_name, salary, dept_id, RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dept_rank FROM employees;7.2 公用表表达式(CTE)
-- 递归查询组织架构 WITH RECURSIVE org_tree AS ( SELECT * FROM departments WHERE dept_id = 1 UNION ALL SELECT d.* FROM departments d JOIN org_tree ot ON d.parent_id = ot.dept_id ) SELECT * FROM org_tree;8. 运维监控语句集锦
8.1 性能诊断
-- 查看慢查询 SELECT * FROM mysql.slow_log WHERE start_time > NOW() - INTERVAL 1 DAY ORDER BY query_time DESC LIMIT 10; -- 当前连接数统计 SHOW STATUS LIKE 'Threads_connected';8.2 容量规划
-- 表空间分析 SELECT table_schema, table_name, ROUND(data_length/1024/1024, 2) AS data_mb, ROUND(index_length/1024/1024, 2) AS index_mb FROM information_schema.TABLES ORDER BY (data_length + index_length) DESC;这套监控语句帮助我们提前3个月预测到磁盘将满的情况,避免了线上事故。
9. 备份与恢复关键命令
-- 逻辑备份单表 mysqldump -u root -p --single-transaction db_name table_name > table.sql -- 时间点恢复 mysqlbinlog --start-datetime="2023-08-01 00:00:00" binlog.000123 | mysql -u root -p去年机房断电导致数据损坏,我们通过binlog恢复了故障前1秒的所有数据,客户甚至没有感知到异常。
10. 安全审计语句
-- 用户权限审查 SELECT * FROM mysql.user WHERE User NOT IN ('root','mysql.sys'); -- 密码强度检查 SELECT user, plugin FROM mysql.user WHERE plugin = 'mysql_native_password' AND LENGTH(authentication_string) < 50;这套审计方案帮助某金融客户通过了等保三级认证,发现了6个弱密码账户。