当前位置: 首页 > news >正文

013、数据库性能优化:索引、查询与连接池

013、数据库性能优化:索引、查询与连接池


一、从一次慢查询说起

上周排查一个线上问题,接口响应时间从平均 50ms 飙到 2 秒以上。打开慢查询日志,抓到一条 SQL:

SELECT*FROMorder_detailWHEREuser_id=10086ANDstatus=1ANDcreate_time>'2024-01-01'ORDERBYupdate_timeDESCLIMIT20;

表里有 300 万条数据,这条查询居然扫了 280 万行。第一反应是索引问题,一看表结构,果然只在id上建了主键索引。问题就出在这里——没有为查询条件建立合适的索引


二、索引不是越多越好

很多人觉得索引能加速查询,就拼命建索引。我见过一张表建了 15 个索引,写入速度慢得像蜗牛。索引的本质是用空间换时间,每个索引都是一棵 B+ 树,写入时要维护所有索引树。

踩坑案例:曾经在status字段上单独建索引,查询依然慢。后来明白,status只有 0/1 两种值,区分度太低,MySQL 优化器可能直接忽略这个索引。

正确姿势:对上面那条慢查询,我建的是联合索引:

ALTERTABLEorder_detailADDINDEXidx_user_status_time(user_id,status,create_time);

注意字段顺序:

  • user_id放第一,因为等值查询,区分度高
  • status放第二,虽然区分度低,但能利用索引过滤
  • create_time放最后,用于范围查询

别这样写

-- 顺序乱放,索引可能失效ADDINDEXidx_time_status_user(create_time,status,user_id);

三、查询优化的几个细节

1. 避免 SELECT *

-- 坏习惯:读所有字段SELECT*FROMlarge_tableWHERE...-- 好习惯:只取需要的SELECTid,name,statusFROMlarge_tableWHERE...

多一个字段就可能多一次回表操作,尤其 TEXT/BLOB 字段。

2. 小心 JOIN 陷阱

-- 大表 JOIN 大表,性能灾难SELECT*FROMtable_a aJOINtable_b bONa.id=b.a_idWHEREa.create_time>'2024-01-01';-- 先过滤再 JOINSELECT*FROM(SELECTid,nameFROMtable_aWHEREcreate_time>'2024-01-01')aJOINtable_b bONa.id=b.a_id;

3. 分页的坑

-- 深度分页,越往后越慢SELECT*FROMtableLIMIT1000000,20;-- 优化:记住上一页最后一条的 idSELECT*FROMtableWHEREid>1000000LIMIT20;

四、连接池:别小看这池子水

早期项目直接每次查询创建连接,QPS 到 500 就报Too many connections。后来上了连接池,稳定支撑 3000+ QPS。

关键参数配置(以 HikariCP 为例)

# 这里踩过坑:maxLifetime 设太短会导致连接频繁重建hikari:maximum-pool-size:20# 根据业务调整,不是越大越好minimum-idle:10max-lifetime:1800000# 30分钟,别低于 30sconnection-timeout:3000# 获取连接超时时间idle-timeout:600000# 空闲连接超时

监控指标要看

  • 活跃连接数
  • 空闲连接数
  • 等待获取连接的线程数
  • 连接创建/销毁频率

五、ORM 的甜与苦

用 Django ORM 或 SQLAlchemy 确实方便,但生成的 SQL 可能很蠢。一定要开启 query log,定期检查。

案例

# 这样写会产生 N+1 查询users=User.objects.filter(age__gt=20)foruserinusers:print(user.profile.address)# 每次循环都查一次 profile# 优化:使用 select_relatedusers=User.objects.select_related('profile').filter(age__gt=20)

六、个人经验包

  1. 索引创建后要验证:用EXPLAIN看执行计划,关注type字段(至少 range 以上),rows越小越好。

  2. 定期清理慢查询:每周看一次慢查询日志,超过 200ms 的都要分析。

  3. 连接池不是银弹:连接数设置要考虑数据库最大连接数(max_connections),留 20% 余量给管理连接。

  4. 冷热数据分离:3 个月前的订单数据归档到历史表,主表只留热数据。

  5. 压测时关注数据库:CPU 使用率超过 70% 或连接数飙高,就要考虑优化了。

  6. 开发环境用真实数据量测试:用 100 条数据测不出性能问题,至少灌 10 万条。


数据库优化是个细致活,需要持续观察和调整。最好的优化时机是设计阶段,最贵的优化时机是上线以后。先理清业务查询模式,再动手加索引,别凭感觉来。

http://www.jsqmd.com/news/630824/

相关文章:

  • 从‘抢茅台’到‘秒杀活动’,聊聊Guava令牌桶算法背后的那些‘坑’与最佳实践
  • 从USB充电到HDMI传4K:聊聊PCB板上那些‘隐形’的100Ω和90Ω差分线
  • StructBERT情感识别效果惊艳展示:高置信度正负中性判别真实文本案例集
  • S32K144新手必看:用SDK库函数5分钟搞定GPIO点灯和按键读取
  • AI Coding越来越强,我们还有必要学Processing吗? · 创意编程呛
  • 【笔面试算法学习专栏】回溯算法·进阶两题精讲(LeetCode 39. 组合总和、40. 组合总和 II)
  • 别再只用connectWifi了!微信小程序连接Wi-Fi的完整避坑指南(附getConnectedWifi实战代码)
  • 告别预制镜像:为OrangePi Zero 3构建自定义引导链(U-Boot + BL31 + SCP)实战详解
  • Dify知识库效率翻倍秘诀:巧用元数据过滤,让RAG问答又快又准
  • Qt监控项目实战:用libvlc+OpenGL渲染多路视频流,CPU占用率直降80%
  • TP2855视频解码芯片寄存器配置实战:从亮度调节到色彩锁相环优化
  • GLM-4.1V-9B-Base企业级应用:基于SpringBoot构建智能内容审核系统
  • 可靠性设计:元器件、零部件、原材料的全生命周期管理策略
  • 5分钟搞懂匹配网络:小样本学习中的注意力机制实战指南
  • 告别Miniconda3:在Ubuntu 22.04上两种干净卸载方法的实测对比
  • 避开这些坑!用FPGA驱动安森美PYTHON5000图像传感器的实战指南
  • Phi-4-mini-reasoning开源推理实践:vLLM高效部署与Chainlit前端调用详解
  • FPGA时序约束入门:从“代码能跑多快”到“告诉工具我要跑多快”的思维转变
  • 【PZ-ZU15EG-KFB】璞致ZYNQ UltraScale+ MPSOC核心板:工业级FPGA开发实战指南
  • V4L2开发避雷:为什么你的ioctl调用总返回EBUSY?从streamon到buffer管理的完整解决方案
  • CTF逆向:BFS算法秒解二维四向迷宫实战指南
  • 20252806 2024-2025-2 《网络攻防实践》实验三
  • FPGA新手必看:Xilinx GTX收发器VMGTAVCC供电设计避坑指南
  • 2026年市场诚信的OK镜专用无菌冲洗液源头厂家推荐,成分天然,呵护眼睛健康无负担 - 品牌推荐师
  • FastAPI项目安全升级:用SQLModel多模型策略保护敏感字段(比如用户密码和API密钥)
  • CSS如何做一个具有渐变背景的渐显文字_通过背景裁剪实现炫彩字体css
  • Arduino Nano 33 BLE Sense离线语音唤醒SDK详解
  • 从零到一:在HomeAssistant中为ESP8266设备注入灵魂(配置/编译/部署全流程)
  • SAP PS配置避坑指南:OPSA项目参数文件里的‘基本控制’到底怎么配?
  • anaconda navigator启动时一直卡在 loading applications 页面