5000字干货,教你写一手好SQL!
共 3087字,需浏览 7分钟
·
2020-12-11 01:06
由于公众号的改版,为了保证你们第一时间能看到我的文章,大家记得将公众号 加星标置顶 哦!
MySQL 性能
①最大数据量
select field_1,field_2 from table where id < #{prePageMinId} order by id desc limit 20
②最大并发数
max_used_connections / max_connections * 100% = 3/100 *100% ≈ 3%
show variables like '%max_connections%';
show variables like '%max_user_connections%';
[mysqld]
max_connections = 100
max_used_connections = 20
③查询耗时 0.5 秒
④实施原则
充分利用但不滥用索引,须知索引也消耗磁盘和 CPU。
不推荐使用数据库函数格式化数据,交给应用程序处理。
不推荐使用外键约束,用应用程序保证数据准确性。
写多读少的场景,不推荐使用唯一索引,用应用程序保证唯一性。
适当冗余字段,尝试创建中间表,用应用程序计算中间结果,用空间换时间。
不允许执行极度耗时的事务,配合应用程序拆分成更小的事务。
预估重要数据表(比如订单表)的负载和数据增长态势,提前优化。
数据表设计
①数据类型
如果长度能够满足,整型尽量使用 tinyint、smallint、medium_int 而非 int。
如果字符串长度确定,采用 char 类型。
如果 varchar 能够满足,不采用 text 类型。
精度要求较高的使用 decimal 类型,也可以使用 BIGINT,比如精确两位小数就乘以 100 后保存。
尽量采用 timestamp 而非 datetime。
②避免空值
③Text 类型优化
索引优化
索引分类如下:
普通索引:最基本的索引。
组合索引:多个字段上建立的索引,能够加速复合查询条件的检索。
唯一索引:与普通索引类似,但索引列的值必须唯一,允许有空值。
组合唯一索引:列值的组合必须唯一。
主键索引:特殊的唯一索引,用于唯一标识数据表中的某一条记录,不允许有空值,一般用 primary key 约束。
全文索引:用于海量文本的查询,MySQL 5.6 之后的 InnoDB 和 MyISAM 均支持全文索引。由于查询精度以及扩展性不佳,更多的企业选择 Elasticsearch。
索引优化原则:
分页查询很重要,如果查询数据量超过 30%,MySQL 不会使用索引。
单表索引数不超过 5 个、单个索引字段数不超过 5 个。
字符串可使用前缀索引,前缀长度控制在 5-8 个字符。
字段唯一性太低,增加索引没有意义,如:是否删除、性别。
合理使用覆盖索引,如下所示:
select login_name, nick_name from member where login_name = ?
SQL 优化
①分批处理
update status=0 FROM `coupon` WHERE expire_date <= #{currentDate} and status=1;
int pageNo = 1;
int PAGE_SIZE = 100;
while(true) {
ListbatchIdList = queryList('select id FROM `coupon` WHERE expire_date <= #{currentDate} and status = 1 limit #{(pageNo-1) * PAGE_SIZE},#{PAGE_SIZE}');
if (CollectionUtils.isEmpty(batchIdList)) {
return;
}
update('update status = 0 FROM `coupon` where status = 1 and id in #{batchIdList}')
pageNo ++;
}
②操作符 <> 优化
select id from orders where amount != 100;
(select id from orders where amount > 100)
union all
(select id from orders where amount < 100 and amount > 0)
③OR 优化
select id,product_name from orders where mobile_no = '13421800407' or user_id = 100;
(select id,product_name from orders where mobile_no = '13421800407')
union
(select id,product_name from orders where user_id = 100);
④IN 优化
select id from orders where user_id in (select id from user where level = 'VIP');
select o.id from orders o left join user u on o.user_id = u.id where u.level = 'VIP';
⑤不做列运算
select id from order where date_format(create_time,'%Y-%m-%d') = '2019-07-01';
select id from order where create_time between '2019-07-01 00:00:00' and '2019-07-01 23:59:59';
⑥避免Select All
⑦Like 优化
SELECT column FROM table WHERE field like '%keyword%';
SELECT column FROM table WHERE field like 'keyword%';
⑧Join 优化
⑨Limit 优化
select * from orders order by id desc limit 100000,10
耗时0.4秒
select * from orders order by id desc limit 1000000,10
耗时5.2秒
select * from orders where id > (select id from orders order by id desc limit 1000000, 1) order by id desc limit 0,10
耗时0.5秒
select id from orders where id between 1000000 and 1000010 order by id desc
耗时0.3秒
其他数据库
往期资源回顾 需要可自取
推荐阅读
点个[在看],是对杰哥最大的支持!