数据库分表分库;做完查询反而更慢

一张跑了好几年的大表,拆成好几张之后,SQL 基本没动,上线没两天监控就开始叫:接口耗时往上顶,慢查询列表里冒出一堆以前压根没见过的语句。数据库分表分库做完反而更慢,这不是玄学,也不该甩锅给中间件,九成情况是拆的动作完成了,配套的查询路径还停在单表时代。

数据库优化

数据库分表分库做完反而更慢,先别急着怪硬件

见过太多人第一反应是加内存、升配置、换更贵的盘。钱花出去了,曲线一动不动。为啥,瓶颈不在机器上——原来是 1 条语句扫一张表,现在中间件把它拆成若干条发给不同分片,再拼回来,网络往返、结果集合并、排序全压在应用或者中间件这一层。原来一句搞定的事,变成了好几趟来回加一次归并。数据总量没少,工作量反而多了,慢是必然的,问题只在于这份慢换回来的容量值不值。

分片键选错,后面全是补丁

分片键这东西选错,改起来比重做还难受。最常见的坑是按创建时间分片,用户查自己的历史记录,条件是 user_id,中间件没法定位,只能往所有分片广播,一个请求打穿全部分片。还有人按状态分片——待付款、已付款、已发货,数据分布完全跟着业务节奏跑,某段时间全堆在待付款那一片,别的片闲着发慌。选分片键的标准特别土:看 WHERE 里出现频率最高、又能保证数据摊得匀的那个字段。用户维度就用 user_id,租户维度就用 tenant_id。别为了“看着均匀”挑一个查询根本用不上的字段,那是给自己挖坑。

跨库 JOIN 和深分页,两个大坑

单表时一个 JOIN 就完事,拆完两张表落在不同库,JOIN 直接做不了。有人就在应用层写循环,一条条查回来再拼——标准的 N+1,本来一次网络往返的活变成几百次。分页同理,LIMIT 十万加二十这种写法单表上都够呛,跨分片之后中间件得从每片各取十万多条,再在内存里排完截取,内存和 CPU 一起飙。这类语句要么改成游标翻页(where id > 上一页最后那个 id),要么把要一起查的数据冗余进同一个分片,没有第三条路。

索引没跟着搬,等于白拆

拆表脚本跑得挺顺,索引忘了建。每张子表都是裸表,查询照样全表扫,只是从扫一张大表变成扫好几张小表再合并。更隐蔽的是唯一约束:单表上一个 UNIQUE 能保证手机号不重复,拆完唯一性只在片内有效。有人图省事在应用层先查“存在就不插入”,并发一上来照样插重。这种约束要么用全局唯一 ID 兜,要么单开一张映射表来保证。数据库分表分库做完反而更慢,有时候真不是 SQL 写得差,是这些底下的东西没搬过去。

连接池照着原样抄,数据库先被自己人压垮

这条最容易被漏掉。原来连一个库,连接池配几十个。拆成多个库之后配置一抄,总连接数翻了几倍。数据库的最大连接数有上限,超了就是排队、报错、连锁雪崩。拆库之后连接池得重算:按每片能扛多少加上中间件自身的开销来配,宁可小一点也别照抄。顺便提醒一句,连接数不是越大越快,多数时候是被自己的空闲连接拖死的。

报表和统计,走错门就得扫全场

后台的统计页往往先崩。COUNT、SUM、按天汇总这类语句,在分片环境里基本等于全库扫一遍。办法老土但管用:单独搞一张汇总表,定时任务跑批写进去,页面只读这张表;实时性要求高的,就在写入的时候顺手增量算。非要实时 COUNT 全量数据的,靠分表分库救不了,得换思路,比如把统计需求单独拉一条链路出去。

上线前能补的几件事

压测别拿几千条测试数据糊弄,数据分布要贴近真实,热点用户、热点分片都得造出来。慢查询日志开起来,重点盯跨分片语句,尤其是那种一下打穿全部分片的。监控里把中间件耗时单独拉一根线,别和应用耗时混在一起看,混着看永远找不到真凶。还有回滚路径,拆完发现不对能不能退回去,这事上线前就要想清楚,不是出事之后现场拍脑袋。

分表分库本质上是拿查询复杂度去换单表容量。查询简单的业务——基本都是按主键或分片键取单条——分完确实会快;查询花样多、条件乱飞的,分完变慢是常态,只能靠冗余表、汇总表、异步去补。所以真动手之前,先把线上慢查询日志翻一遍,看排名靠前的那批语句能不能落在同一个分片键上。能,就放心拆;不能,先别急着动刀,把查询理顺了再说。

【版权声明】:本站内容若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!

赞 (0)
爱家的头像爱家
证书接口调用失败?多半是信任链断了
上一篇 2026-11-13 07:11
惠普笔记本的USB端口通常位于哪个位置?
下一篇 2024-08-28 09:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

广告合作

QQ:14239236

在线咨询: QQ交谈

邮件:asy@cxas.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信