❝开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共3300人左右 1 + 2 + 3 + 4 +5 + 6 + 7 + 8 +9)(1 2 3 4 5 6 7群均已爆满,开8群近400 9群 200+,开10群PolarDB专业学习群100+)
上期说完MSSQL的优化后,相信科技的力量让SQL优化更加简单深入人心,但如果你用的是MySQL,瞬间一种天堂到地狱的赶脚。咱们今天就说说磨练人心性的MySQL SQL优化。
咱们也有四句真言,给MySQL SQL优化
参数调整挺重要,查询方式很重要,
大表你的要会拆,架构优化少不了,
善用SQL的改写,避免中间大结果,
尽量升级8.0 ,更好引擎效率高。
熟悉MySQL的同学对于SQL优化中第一个问题并不是SQL本身的这个问题应该很清楚,早期玩MySQL的都是现在参数的调整里面先玩一顿,然后在转向表的拆分,最后才是SQL本身。
第一个参数与你的CPU有关,innodb_buffer_pool_instances,提高并发度使用内存的灵活性,有效的将buffer pool分片,在高并发写的情况下,减少latch的竞争。CPU 核心越多,内存越大,这个部分分的就越多,具体优化这个参数的文档很多,可以去读一读。
剩下的就是 join_buffer_size, read_buffer_size,read_rnd_buffer_size,这些都是主导读取数据时的线程的缓存大小,对于order by group by 顺序扫描以及大表的join等都有提升效率的功能。具体与每个数据库承载的业务和撰写的SQL复杂度和调取数据量有关。
同时对于optimizer_switch , 里面那一堆的参数也要有所取舍,尤其对于group by 语法的参数在5.X 升级到8的兼容性要进行测试,否则升级版本在这块可能会失败,导致升级回退,sort_buffer_size, tmp_table_size等在需要排序和临时表的时候,也要设置对应的内存帮助加速查询。
在MySQL优化中,更多的是拆表,且集中在逻辑业务拆分,而不是使用MySQL的分区表,到现在我还是这个观点,MySQL不要用分区表,原因之前的文章有写过。
同时老的MySQL的DBA 还会思考主键的问题,主键越小越好,这与MySQL的原理息息相关,更小的主键会让数据更多在Btree的上层,而不是下层,分表的原因也是这个,所以那时我们会纠结主键大小的问题。
关于改写SQL的问题,在MySQL是家常便饭,尤其是一些军规和什么SQL撰写的要求。列两条让传统的MySQL DBA回忆一下。
避免 SELECT *,SELECT * 会取所有列,可能让中间结果变大。改写成只取需要的列:SELECT id, name FROM users。
EXISTS 优于 IN(大子查询时)
IN (SELECT …) 在结果集很大时会生成临时表。改写:EXISTS (SELECT 1 FROM … WHERE condition)。
JOIN 代替子查询
有时子查询会产生巨大的中间结果。改写成 JOIN 并配合索引,减少中间表
避免大范围 OR,用 UNION ALL
WHERE col = 'a' OR col = 'b' 可能导致索引失效。
比如下面的SQL
SELECT u.user_id, u.user_name
FROM users u
WHERE u.user_id IN (
SELECT o.user_id
FROM orders o
WHERE o.order_date >= '2024-01-01'
GROUP BY o.user_id
HAVING SUM(o.amount) > 1000
);
可以改写成
SELECT u.user_id, u.user_name
FROM users u
JOIN (
SELECT o.user_id
FROM orders o
WHERE o.order_date >= '2024-01-01'
GROUP BY o.user_id
HAVING SUM(o.amount) > 1000
) t ON u.user_id = t.user_id;
还可以改写成
SELECT u.user_id, u.user_name
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.user_id
AND o.order_date >= '2024-01-01'
GROUP BY o.user_id
HAVING SUM(o.amount) > 1000
);
留一个小问题,这两个方案有什么不同,第二个方案适合什么场景??
最后一句,建议升级到8.0版本的原因,我简单说几个
1 Hash join
2 倒序索引
3 窗口函数提供
4 CTE通用表达式的提供
5 虚拟列和JOIN 的执行计划的完善
6 使用更好的直方图统计方式
这里举几个简单的例子
1 Hash Join
EXPLAIN FORMAT=tree
SELECT o.order_id, c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;
在8.018这个版本后,支持Hash join,当有两个大表JOIN的时候,可以使用hash join,而不是nested loop 的方式
2 倒序排序 早先MYSQL不支持倒序索引,全部都是正序,倒序SQL执行效率低
CREATE INDEX idx_order_date_desc ON orders(order_date DESC);
EXPLAIN SELECT * FROM orders ORDER BY order_date DESC LIMIT 10;
3 窗口函数的提供
在MYSQL8提供了一些先进的函数,比如下面的SQL,你看看
SELECT customer_id, order_date,
@rn := IF(@prev_customer = customer_id, @rn + 1, 1) AS rn,
@prev_customer := customer_id
FROM (
SELECT customer_id, order_date
FROM orders
ORDER BY customer_id, order_date
) t,
(SELECT @rn := 0, @prev_customer := NULL) vars;
如果到了MYSQL8 可以写成
SELECT customer_id, order_date,
ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY order_date) AS rn
FROM orders;
当然最后还有我们熟悉的虚拟列,这个部分文章较多就不赘述了。
在早先的MySQL DBA值钱的原因之一,是要动一些架构的知识,也就是会逻辑业务分库,在懂得业务,配合架构知识,对于整体数据的一个拆分,这是早先 MSSQL ,ORACLE DBA 不具备的知识,所以 MySQL DBA本身值钱的部分是对于整体知识的把控,而到了现在这些被架构师拿走了,MySQL DBA的辉煌也随着MySQL本身的迭代和本身的数据处理能力的增强,成为了过去式。
这里举一个例子 ,
比如电商网站中的
用户表
users
(千万级用户)商品表
products
(百万级商品)订单表
orders
(每天千万级写入)支付表
payments
(高频更新)
单库单实例:所有表都放在一台 MySQL 里,查询和写入争抢 I/O。
业务无区分:用户、商品、订单、支付混在一起,业务部门谁动谁的表都不清晰。
高并发写入瓶颈:尤其是订单表,单表写入超过千万行后,insert/update/索引维护非常慢。
备份与运维困难:mysqldump 或全库备份,动辄几个小时。
用户数据(读多写少)
商品数据(读多写少,缓存可用)
订单 & 支付(写多 + 热点操作)
user_db
→ 用户库product_db
→ 商品库order_db
→ 订单库payment_db
→ 支付库
按 用户 ID 取模
order_db_00
~order_db_15
(16 个库,按 user_id % 16 拆分)
这样分库分表后,整体的单表会被分到不同的实例,即使在同一个实例,也可能不在一个逻辑库,即使在一个逻辑库,也会在不同的逻辑表。
单表压力从 亿级 → 千万级,性能明显提升。
高频写入的订单库 吞吐量翻倍,单机 QPS 从几千提升到几万。
备份/恢复只针对单库,时间缩短 数小时 → 数分钟。
业务部门之间的表操作更清晰,架构层次分明。
总体MYSQL的优化是一个立体化,架构化,形式不固定化的方案结合体,相对其他的数据库,可能“歪门邪道”会多一些,但怎么优化的目的都是一样,快速的解决业务的需求。
微软动手了,联合OpenAI + Azure 云争夺AI服务市场
“当复杂的SQL不再需要特别的优化”,邪修研究PolarDB for PG 列式索引加速复杂SQL运行
“合体吧兄弟们!”——从浪浪山小妖怪看OceanBase国产芯片优化《OceanBase “重如尘埃”之歌》
未知黑客通过SQL SERVER 窃取企业SAP核心数据,影响企业运营
那个MySQL大事务比你稳定,主从延迟低,为什么? Look my eyes! 因为宋利兵宋老师
非“厂商广告”的PolarDB课程:用户共创的新式学习范本--7位同学获奖PolarDB学习之星
说我PG Freezing Boom 讲的一般的那个同学,专帖给你,看看这次可满意
这个 PostgreSQL 让我有资本找老板要 鸡腿 鸭腿 !!
OceanBase Hybrid search 能力测试,平换MySQL的好选择
HyBrid Search 实现价值落地,从真实企业的需求角度分析 !不只谈技术!
OceanBase 光速快递 OB Cloud “MySQL” 给我,Thanks a lot
从“小偷”开始,不会从“强盗”结束 -- IvorySQL 2025 PostgreSQL 生态大会
被骂后的文字--技术人不脱离思维困局,终局是个 “死” ? ! ......
个群2025上半年总结,OB、PolarDB, DBdoctor、爱可生、pigsty、osyun、工作岗位等
从MySQL不行了,到乙方DBA 给狗,狗都不干? 我干呀!
SQL SERVER 2025发布了, China幸亏有信创!
MongoDB 麻烦专业点,不懂可以问,别这么用行吗 ! --TTL
PostgreSQL 新版本就一定好--由培训现象让我做的实验
删除数据“八扇屏” 之 锦门英豪 --我去-BigData!
写了3750万字的我,在2000字的OB白皮书上了一课--记 《OceanBase 社区版在泛互场景的应用案例研究》
疯狂老DBA 和 年轻“网红” 程序员 --火星撞地球-- 谁也不是怂货
和架构师沟通那种“一坨”的系统,推荐只能是OceanBase,Why ?
跟我学OceanBase4.0 --阅读白皮书 (OB分布式优化哪里了提高了速度)
跟我学OceanBase4.0 --阅读白皮书 (4.0优化的核心点是什么)
跟我学OceanBase4.0 --阅读白皮书 (0.5-4.0的架构与之前架构特点)
跟我学OceanBase4.0 --阅读白皮书 (旧的概念害死人呀,更新知识和理念)
MongoDB 相关文章
MongoDB “升级项目” 大型连续剧(4)-- 与开发和架构沟通与扫尾
MongoDB “升级项目” 大型连续剧(3)-- 自动校对代码与注意事项
MongoDB “升级项目” 大型连续剧(2)-- 到底谁是"der"
MongoDB “升级项目” 大型连续剧(1)-- 可“生”可不升
MongoDB 大俗大雅,上来问分片真三俗 -- 4 分什么分
MongoDB 大俗大雅,高端知识讲“庸俗” --3 奇葩数据更新方法
MongoDB 大俗大雅,高端的知识讲“通俗” -- 2 嵌套和引用
MongoDB 大俗大雅,高端的知识讲“低俗” -- 1 什么叫多模
MongoDB 合作考试报销活动 贴附属,MongoDB基础知识速通
MongoDB 使用网上妙招,直接DOWN机---清理表碎片导致的灾祸 (送书活动结束)
MongoDB 2023年度纽约 MongoDB 年度大会话题 -- MongoDB 数据模式与建模
免费PolarDB云原生课程,听课“争”礼品,重塑云上知识,提高专业能力
“PostgreSQL” 高性能主从强一致读写分离,我行,你没戏!
POLARDB 添加字段 “卡” 住---这锅Polar不背
PolarDB 版本差异分析--外人不知道的秘密(谁是绵羊,谁是怪兽)
PolarDB 答题拿-- 飞刀总的书、同款卫衣、T恤,来自杭州的Package(活动结束了)
PolarDB for MySQL 三大核心之一POLARFS 今天扒开它--- 嘛是火
PostgreSQL 无服务 Neon and Aurora 新技术下的新经济模式 (翻译)
“PostgreSQL” 高性能主从强一致读写分离,我行,你没戏!
全世界都在“搞” PostgreSQL ,从Oracle 得到一个“馊主意”开始
PostgreSQL 加索引系统OOM 怨我了--- 不怨你怨谁
PostgreSQL “我怎么就连个数据库都不会建?” --- 你还真不会!
PostgreSQL 稳定性平台 PG中文社区大会--杭州来去匆匆
PostgreSQL 分组查询可以不进行全表扫描吗?速度提高上千倍?
POSTGRESQL --Austindatabaes 历年文章整理
PostgreSQL 查询语句开发写不好是必然,不是PG的锅
MySQL相关文章





