慢查询优化:
mysql需要开启慢查询,默认是关闭的,定义慢查询时间 默认是10s 项目中一般用1s,以及慢查询日志的存储地址
可以使用explain命令分析sql语句
(1)首先看查询的条件字段有没有创建索引,如果没有可以考虑加索引
(2)如果已经加了索引但是没有用到,看一下是不是因为sql语句的查询写的有问题导致索引没有生效,比如使用了is null 、!=或使用了函数计算
(3)如果索引已经生效,可以分析下sql是不是太复杂了,可以考虑对sql进行拆分,或者考虑优化sql语句
(4)最后如果这些方式效果都不理想,那就要从业务角度看一下能不能换一种查询方式。
mysql order by中索引的使用,当表中存在联合索引,如id为主键,a、b有组合索引,c、d为普通字段,那么使用
select a from table order by b、select b from table order by a、 select id、a from table order by a,b 、select id,a,b from table order by b,a等都是使用索引的,也就是说order by中是普通索引或联合索引(联合索引中的任意一个任意顺序),查询字段为对应的索引或主键那么order by都是使用索引的,但如果查询字段(可以有id)或order by中出现了不存在于组合索引的字段,那么查询就不再使用索引了。
group by中索引使用,如果表中有a、b、c、d4个字段,ab有组合索引,c有普通索引,d无索引,那么当对a、ab、c分别进行group by的时候是可以使用到索引的,如果group by的时候加入了非索引字段就不会再使用索引如:ad、cd等,同时单独对b、ba这种组合也没有使用索引
1.当查询速度变慢时首先可以考虑对sql进行优化,即建立合适的索引及恰当的使用这些索引:
(1)如果语句中有group by、order by,可以在其所涉及的列上建立索引,避免全局扫描
(2)select id from t where num is null ,where中最好避免对字段进行null判断,将会使引擎放弃使用索引而全局扫描,可以在设计数据表时对所有字段给定一个默认值,int可以设为-1,string为“”,避免为null
(3)应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
(4)应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
(5)select id from t where name like ‘%abc%’,该语句也会进行全文扫描,可以尝试使用全文索引,https://www.cnblogs.com/tommy-huang/p/4483684.html
(6)不要使用select *,查询要带具体的字段
(7)在where条件中不要字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描
2.建好合适的索引一般百万级别数据量的表可以正常使用,但如果数据量持续增加,那么可以考虑进行分表、分库:
以我现在正在维护的项目,需要对项目进行埋点统计日常UV、PV、交易记录、充值记录、开户记录等信息,这些数据都需要落库,而UV、PV及充值交易记录的数据量是很巨大的,假如把他们都放在一个表中,数据量不断累加将会十分巨大,项目中结合实际情况,对UV、PV和交易记录等每天数据较大的表采用按季度分表,开户信息按年来分表,即以创建时间为纬度来分表,使用了mycat作为分表中间件,自定义分表规则,需要注意的是分表后再想和其他未进行分表的数据表进行级联查询将会很困难,所以要进行良好的设计。
而分库主要是根据业务的不同,将不同业务所涉及的数据存储在不同的数据库中,微服务可以不同的服务对应不同的数据库。如果在同一个服务中需要查询两个库中的数据需要配置不同的数据源,并且数据库之间是数据隔离的。
3.集群搭建:(这个是个人理解,我没有实际搭建过)
如果想要保证数据库的高可用,避免单个数据库服务器宕机导致无法正常提供服务的情况发生,可以搭建数据库集群,以mysql为例,假如现在有三台服务器,分别在上面部署三个mysql实例,采用主从的方式,进行读写分离,主服务器提供读和写服务,而从服务器提供读和备份服务。
同时使用Nginx或Haproxy提供反向代理服务,使用Keepalived来进行代理服务健康检测及对外提供统一IP的功能,以此来实现高可用负载均衡。
当请求到来时,Nginx会根据负载算法,将请求分发到不同的mysql服务器上去,通过健康检查来检测被代理服务器的健康状态,如果某一节点出现故障则会被移除,当前恢复后会被重写纳入集群。nginx通过在配置文件中添加反向代理地址,以代理服务器的身份接受客户端发送过来的请求,将请求转发给集群中的某台mysql服务器,并获取操作结果返还给客户端;在外界看来nginx就是一个正常的服务器,不过它只负责请求的转发,并不实现具体的业务处理。同时nginx支持多种负载转发算法,如常见的轮询、权重、ip_hash算法等。
使用Nginx之后,动态负载问题被解决,但另一个问题又随之产生,一旦Nginx出现故障,虽然mysql服务器可以正常工作,但整个服务也是不可用的,客户端不会自动去访问原始的mysql服务器。为了处理该异常,可以采取Nginx服务器集群的方式,但加机器就会出现多个代理ip,如何保证客户端仅向单个ip发送请求又保证服务端的代理机器为多台,这就是服务单点问题。针对这种情况,我们为每个Nginx配置KeepAlived,它会统一向外提供一个VIP以满足正常服务。当有请求到来时会有一个KeepAlived获取vip,那么它所属的nginx则提供代理服务,并且该KeepAlived需要定时向其他KeepAlived服务发送数据包,报告自己的健康状态,如果发现异常的话,其他服务将会夺取VIP。