来,教你写一手好SQL!(一)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 导出日志后分析,主要原因竟然是没有命中索引和没有分页处理。其实这是非常低级的错误,我不禁后背一凉,团队成员的技术水平亟待提高啊。改造这些 SQL 的过程中,总结了一些经验分享给大家,如果有错误欢迎批评指正。

MySQL 性能


①最大数据量


抛开数据量和并发数,谈性能都是耍流氓。MySQL 没有限制单表最大记录数,它取决于操作系统对文件大小的限制。

1.jpg

《阿里巴巴 Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐分库分表。


性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL 配置、数据表设计、索引优化。500 万这个值仅供参考,并非铁律。


我曾经操作过超过 4 亿行数据的单表,分页查询最新的 20 条记录耗时 0.6 秒,SQL 语句大致是:


select field_1,field_2 from table where id < #{prePageMinId} order by id desc limit 20


prePageMinId 是上一页数据记录的最小 ID。虽然当时查询速度还凑合,随着数据不断增长,有朝一日必定不堪重负。


分库分表是个周期长而风险高的大活儿,应该尽可能在当前结构上优化,比如升级硬件、迁移历史数据等等,实在没辙了再分。对分库分表感兴趣的同学可以阅读分库分表的基本思想。


②最大并发数


并发数是指同一时刻数据库能处理多少个请求,由 max_connections 和 max_user_connections 决定。


max_connections 是指 MySQL 实例的最大连接数,上限值是 16384,max_user_connections 是指每个数据库用户的最大连接数。

MySQL 会为每个连接提供缓冲区,意味着消耗更多的内存。如果连接数设置太高硬件吃不消,太低又不能充分利用硬件。

一般要求两者比值超过 10%,计算方法如下:


max_used_connections / max_connections * 100% = 3/100 *100% ≈ 3%


查看最大连接数与响应最大连接数:


show variables like '%max_connections%';
show variables like '%max_user_connections%';


在配置文件 my.cnf 中修改最大连接数:


[mysqld]
max_connections = 100
max_used_connections = 20


③查询耗时 0.5 秒


建议将单次查询耗时控制在 0.5 秒以内,0.5 秒是个经验值,源于用户体验的 3 秒原则。如果用户的操作 3 秒内没有响应,将会厌烦甚至退出。


响应时间=客户端 UI 渲染耗时+网络请求耗时+应用程序处理耗时+查询数据库耗时,0.5 秒就是留给数据库 1/6 的处理时间。


④实施原则


相比 NoSQL 数据库,MySQL 是个娇气脆弱的家伙。它就像体育课上的女同学,一点纠纷就和同学闹别扭(扩容难),跑两步就气喘吁吁(容量小并发低),常常身体不适要请假(SQL 约束太多)。


如今大家都会搞点分布式,应用程序扩容比数据库要容易得多,所以实施原则是数据库少干活,应用程序多干活:


  • 充分利用但不滥用索引,须知索引也消耗磁盘和 CPU。
  • 不推荐使用数据库函数格式化数据,交给应用程序处理。
  • 不推荐使用外键约束,用应用程序保证数据准确性。
  • 写多读少的场景,不推荐使用唯一索引,用应用程序保证唯一性。
  • 适当冗余字段,尝试创建中间表,用应用程序计算中间结果,用空间换时间。
  • 不允许执行极度耗时的事务,配合应用程序拆分成更小的事务。
  • 预估重要数据表(比如订单表)的负载和数据增长态势,提前优化。


数据表设计


①数据类型


数据类型的选择原则,更简单或者占用空间更小:


  • 如果长度能够满足,整型尽量使用 tinyint、smallint、medium_int 而非 int。
  • 如果字符串长度确定,采用 char 类型。
  • 如果 varchar 能够满足,不采用 text 类型。
  • 精度要求较高的使用 decimal 类型,也可以使用 BIGINT,比如精确两位小数就乘以 100 后保存。
  • 尽量采用 timestamp 而非 datetime。

2.jpg

相比 datetime,timestamp 占用更少的空间,以 UTC 的格式储存自动转换时区。


②避免空值


MySQL 中字段为 NULL 时依然占用空间,会使索引、索引统计更加复杂。从 NULL 值更新到非 NULL 无法做到原地更新,容易发生索引分裂影响性能。


因此尽可能将 NULL 值用有意义的值代替,也能避免 SQL 语句里面包含 is not null 的判断。

③Text 类型优化


由于 Text 字段储存大量数据,表容量会很早涨上去,影响其他字段的查询性能。建议抽取出来放在子表里,用业务主键关联。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
SQL 数据挖掘
SQLBolt,一个练习SQL的宝藏网站
SQLBolt,一个练习SQL的宝藏网站
|
2月前
|
SQL 资源调度 分布式计算
一个SQL任务的一生
一条SQL语句的执行究竟经历了哪些过程?作者作为一个刚入职的大数据研发新人对SQL任务执行整个流程进行了整理,本文就作者学习内容和体会供大家参考。
|
5月前
踏踏实实练习SQL--day09
踏踏实实练习SQL--day09
|
5月前
|
SQL 数据库 数据库管理
《SQL必知必会》读后感(一)
《SQL必知必会》读后感(一)
36 0
|
5月前
踏踏实实练习SQL--day08
踏踏实实练习SQL--day08
|
5月前
踏踏实实练习SQL--day05
踏踏实实练习SQL--day05
|
SQL NoSQL 算法
少侠!如何写一手好 SQL ?
少侠!如何写一手好 SQL ?
118 0
少侠!如何写一手好 SQL ?
|
SQL 存储 缓存
如何写出一手好 SQL ?(2)
最近频繁出现慢SQL告警,执行时间最长的竟然高达5分钟。导出日志后分析,主要原因竟然是没有命中索引和没有分页处理 。
119 0
|
SQL NoSQL 关系型数据库
如何写出一手好 SQL ?(1)
最近频繁出现慢SQL告警,执行时间最长的竟然高达5分钟。导出日志后分析,主要原因竟然是没有命中索引和没有分页处理 。
127 0