GCP MySQL高并发场景下分页计数查询性能急剧下降问题排查求助
GCP MySQL高并发场景下分页计数查询性能急剧下降问题排查求助
大家好,我们团队最近在GCP MySQL上遇到了一个特别头疼的性能问题,折腾了好几天都没摸到根因,想请各位大佬帮忙分析下!
问题背景
我们的数据库是GCP上的MySQL实例,最初配置是4核16G SSD,整个实例总数据量大概50G,但核心业务库只有15G。问题出在白天用户访问高峰时段:大部分页面加载慢到离谱,甚至有页面要40秒以上才能打开。
更诡异的是,单独执行那些慢查询(比如分页用的count统计),耗时也就500ms左右,但一上并发直接雪崩:
- 5个并发查询:平均耗时3秒
- 10个并发:平均7秒
- 20个并发:直接冲到30秒以上...
已做的尝试&优化
- 索引优化:把能加的索引都加了——单字段索引(
issue_date、customer_id、status、workflow每个字段单独加)、复合索引(customer_id+status+workflow+issue_date)都试过。优化后耗时能砍到原来的1/2甚至1/3,但只是把问题往后推了推,高并发下还是炸。 - 资源升级测试:后来临时升级到8核32G,并发表现确实好些——100个并发平均1.5秒,200个并发平均3秒,但总觉得这只是堆资源的“治标”办法,不仅成本更高,而且根本没解决性能雪崩的根源问题。
- 其他尝试:试过加读锁,完全没用;也考虑过预存统计结果,但因为查询里的每个过滤条件都是用户实时输入的,根本没法预存。
典型问题查询示例
下面是一个用来做分页的count查询(已经是我们优化到最简的版本了),单独跑大概150ms,但一并发就拖垮整个库:
select count(i1_0.id) from invoice i1_0 where i1_0.issue_date BETWEEN '2025-01-01' and '2025-07-30' and (i1_0.customer_id = 20 and (i1_0.status, i1_0.workflow) in ((1,1), (2,1), (3,1), (4,1), (5,1), (6,1), (7,1)) );
- 表总数据量大概400万条,这个查询返回的计数是7万左右
- 字段类型:
issue_date是DATE,customer_id是BIGINT,status和workflow是INTEGER - 所有过滤条件都是用户实时输入,没法预存结果
EXPLAIN执行计划
我们跑了这个查询的EXPLAIN,结果如下:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | i1_0 | range | invoice_issue_date_IDX,invoice_customer_id_IDX,invoice_workflow_num_IDX,invoice_status_num_IDX,composite_idx | composite_idx | 23 | 145523 | 100 | Using where; Using index |
表结构(简化版)
下面是invoice表的完整结构(原输入最后有截断,已省略):
CREATE TABLE `invoice` ( `id` bigint NOT NULL AUTO_INCREMENT, `invoice_type_code` varchar(10) NOT NULL COMMENT '', `issue_date` date DEFAULT NULL, `category_code` varchar(3) DEFAULT NULL COMMENT '', `document_currency_code` varchar(3) DEFAULT NULL COMMENT '', `tax_exclusive_amount` decimal(19,6) DEFAULT NULL COMMENT '', `tax_inclusive_amount` decimal(19,6) DEFAULT NULL COMMENT '', `payable_amount` decimal(19,6) DEFAULT NULL COMMENT '', `payment_means_code` varchar(11) DEFAULT NULL COMMENT '', `datecreated` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `dateupdated` timestamp NULL DEFAULT NULL, `tax_amount` decimal(19,6) DEFAULT NULL COMMENT '', `percent` decimal(19,1) DEFAULT NULL, `supplier_id` bigint DEFAULT NULL, `customer_id` bigint DEFAULT NULL, `downloaded` bit(1) DEFAULT NULL COMMENT '', `status_date` datetime DEFAULT NULL COMMENT '', `submission_type` varchar(100) DEFAULT NULL COMMENT '', `tax_type` varchar(100) DEFAULT NULL COMMENT '', `market_number` varchar(100) DEFAULT NULL COMMENT '', `obligation_number` varchar(50) DEFAULT NULL, `comment_status` varchar(2000) DEFAULT NULL, `invoice_number` varchar(20) NOT NULL COMMENT '', `flux_id` bigint DEFAULT NULL, `supplier_service` varchar(100) DEFAULT NULL, `customer_service` varchar(100) DEFAULT NULL, `metadata` longtext NOT NULL COMMENT '', `due_date` date DEFAULT NULL COMMENT '', `iban` varchar(34) DEFAULT NULL COMMENT '', `department_id` bigint DEFAULT NULL, `origin_number` varchar(20) DEFAULT NULL, `supplier_auxiliary_code` varchar(100) DEFAULT NULL COMMENT '', `supplier_type` varchar(100) DEFAULT NULL COMMENT '', `supplier_type_code` varchar(100) DEFAULT NULL COMMENT '', `accounting_date` date DEFAULT NULL COMMENT '', `custom_info` varchar(500) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
疑问&求助
我们团队没有专职DBA,现在完全摸不着头脑:
- 为什么单独查询性能尚可,一并发就雪崩?
- 除了堆资源和加索引,还有什么排查方向?比如锁机制、MySQL配置、或者查询本身还有隐藏的优化点?
- 会不会是InnoDB的某些默认配置不适合高并发场景?
麻烦各位大佬给点思路,谢谢啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

