我们出去面试经常会被问到数据库这一块,而涉及数据库这一块问的最多的就是数据库优化。那么我们怎么做才能做好优化问题呢?今天我们就来聊聊数据库优化那些事。
数据库优化我们一般可以从以下几个方面考虑:
大型项目拆分为小项目,每个项目有自己独立的数据库
原来所有数据表都放在一个数据库节点上,所有的读写请求也都发到这个MySQL上面,所以数据库的负载太高。如果把一个节点的数据库拆分成多个MySQL数据库,这样就可以有效的降低每个MySQL数据库的负载。
分表分库(取模分表、水平分表、垂直分表)
通过取模算法进行水平分表,例如总共有3张表, 1%3=1 放入第一张表,2%3=2,放入低二张表,3%3=0 放入第0张表,相当于用几张表来平分一张表,最好的做法是一张主表,再来几张字表。因为分表不好做分页,数据存放在多张表中,所以需要一张主表用来存放所有的数据,当子表无法满足时采用主表。
读写分离
把对数据库的读写操作分到不同的数据库服务上,以实现数据库的高性能和高并发能力;读写分离最大的弊端就是复制延迟,对于以查询为主的项目比较合适,看项目进行取舍。
数据库表设计遵循三范式
表字段设计
尽量设计成not null,尽量使用数字型字段(如性别,男:1 女:2),若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销,字段长度设计合理,比如邮编,只需要位长度,没必要过长,
用varchar/nvarchar 代替 char/nchar
因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。不要以为 NULL 不需要空间,比如:char(100) 型,在字段建立时,空间就固定了, 不管是否插入值(NULL也包含在内),都是占用 100个字符的空间的,如果是varchar这样的变长字段, null 不占用空间。
sql语句优化
mysql5.7以上的版本,在my.ini中配置慢查询配置
# 启动慢查询日志
slow_query_log = ON
# 慢查询日志存放地方
slow_query_log_file = D:softwaremysqlmysql-5.7.24-winx64datalogsshow.log
# 设置慢查询时间,默认10秒,我们此处设置为1秒,也就是超过1秒就是慢查询
long_query_time = 1
通过下面命令查看下上面的配置:
例如现在我执行 select sleep(2) 沉睡两秒,超过我设置慢查询时间1秒,就会会被记录到慢查询日志中如下
有查询时间,以及慢查询语句,当我们知道慢查询语句了我们就可以针对性优化sql了。而针对sql的优化最多的就是添加索引了
索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。表里面的记录数量越多,这个操作的代价就越高。如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置。
索引原理 :折半查找,减少全表扫描,索引文件中是一个B_tree ,索引的最大查找数为2^n次方,查找数独比较快
我们可以使用explain分析SQL的执行计划。该执行计划可以模拟SQL优化器执行SQL语句,可以帮助我们了解到自己编写SQL是否有用到索引。1)查看执行计划 语法:explain + SQL语句 eg:explain select * from tb;
id :编号
select_type :查询类型
table :表
type :类型
possible_keys :预测用到的索引
key :实际使用的索引
key_len :实际使用索引的长度
ref :表之间的引用
rows :通过索引查询到的数据量
Extra :额外的信息
创建索引 create index index_name on table_name(colum_name...);
索引使用注意事项
select t1.name,(select sex from user u1 where u1.user_id = t1.user_id) as sex from userInfo t1
改成
select t1.name,u1.sex from userInfo left join user u1 on u1.user_id = t1.user_id;
使用"_%"
select * from product where id = "1"
select * from product where id = 1
select id from t where name = 0
select channel_id,count(*) from ep_product GROUP BY channel_id
改成
select channel_id,count(*) from ep_product GROUP BY channel_id order by null
select * from product where sell_price/2 = 100
改成
select * from product where sell_price = 100*2
其他注意事项
insert into user values(1,"张三");
insert into user values(2,"李四");
使用以下方式可以减少语句解析的操作
insert into user values(1,"张三"),(2,"李四");
全部0条评论
快来发表一下你的评论吧 !