数据库优化

0、概要

1、为什么要优化

2、数据库结构优化

3MySQL数据库cpu飙升到500%的话他怎么处理?

4、⼤表怎么优化?某个表有近千万数据,CRUD⽐较慢,如何优化?

5、垂直分表的适⽤场景和优缺点

6、⽔平分表的适⽤场景和优缺点

7MySQL的复制原理以及流程

8、读写分离有哪些解决⽅案?

9、数据表损坏的修复⽅式有哪些?

1、为什么要优化数据库

出现概率:

当然是让我们的数据库更稳、更快、更持久了。

2、数据库结构优化

出现概率: ★★★

其实⼀般业务开发中, 这个关注的不多,估计是⼀些偏极客的团队关注的⽐较多些
使表占⽤尽量少的磁盘空间。减少磁盘I/O次数及读取数据量是提升性能的基础原则。表越⼩,数据读写处理时则需要更少的内存,同时,⼩表的索引占⽤也相对⼩,索引处理也更加快速。

MySQL⽀持不同类型的存储引擎和⾏格式,针对不同类型,业务需求的表应该设置合适的存储引擎及索引⽅法。表设置建议如下:
表列
为列选择最合适(通常最⼩)的数据类型。MySQL 具有许多不同列类型以最⼤化的减少磁盘和内存占⽤。例如,使⽤⾜够⼩的整型来表示⼩范围的⼩整型数据。 MEDIUMINT 通常是⼀个很好的选择,它只占⽤INT 25%,甚⾄更⼩的空间。

如果可能,则将列声明为NOT NULL。声明为NOT NULL,使得优化器能够更好的使⽤索引,并避免了判断NULL的处理,这使得SQL 操作执⾏的更加快速。同时也为每列节省了1 bit的空间。如果确实需要使⽤NULL 值,那么也应该避免所有列都允许NULL

InnoDB 表默认使⽤动态类型(DYNAMIC )的⾏格式。可以通过设置默认⾏格式(innodbdefaultrow_format),或者在表定义(CREATE TABLE  ALTER TABLE)中声明使⽤的⾏格式。

⾏格式
压缩类型的⾏格式,包括COMPACT, DYNAMIC,  COMPRESSED,对于特定操作,减少了存储空间占⽤,但是增加了CPU计算能⼒使⽤。如果主要的负载在缓存命中率及磁盘读写速度,那么这种格式将能够提升数据库反应速度。如果是极端情况负载受限于CPU性能,那么使⽤这种格式则会降低数据库性能。

压缩⾏格式也会对使⽤utf8mb3 或者 utf8mb4格式的变⻓CHAR 类型列存储进⾏优化处理。对于使⽤ROW_FORMAT=REDUNDANT, CHAR(N) 定义的表,每个列值最多占⽤ N × 个字节⻓度。许多语⾔可以使⽤但字节的utf8格式表示,所以规定那个⻓度的定义通常会造成空间浪费。压缩⾏格式定义下,InnoDB 会每⼀个列值分配⼀个N  N× 个字节的空间。

3MySQL数据库cpu飙升到500%的话, 应该怎么处理?

出现概率: ★★★
 cpu 飙升到 500%时,先⽤操作系统命令 top 命令观察是不是 mysqld 占⽤导致的,如果不是,找出占⽤⾼的进程,并进⾏相关处理。

如果是 mysqld 造成的,  show processlist ,看看⾥⾯跑的 session 情况,是不是有消耗资源的 sql 在运⾏。找出消耗⾼的 sql,看看执⾏计划是否准确, index是否缺失,或者实在是数据量太⼤造成。

⼀般来说,肯定要 kill 掉这些线程(同时观察 cpu 使⽤率是否下降),等进⾏相应的调整(⽐如说加索引、改 sql、改内存参数)之后,再重新跑这些 SQL。也有可能是每个 sql 消耗资源并不多,但是突然之间,有⼤量的 session 连进来导致 cpu 飙升,这种情况就需要跟应⽤⼀起来分析为何连接数会激增,再做出相应的调整,⽐如说限制连接数等
show full processlist  可以看到所有链接的情况,但是⼤多链接的 state 其实是 Sleep 的,这种的其实是空闲状态,没有太多查看价值
我们要观察的是有问题的,所以可以进⾏过滤:

-- 查询⾮ Sleep 状态的链接,按消耗时间倒序展示,⾃⼰加条件过滤
select id, db, user, host, command, time, state, info from information_schema.processlist where command != 'Sleep' order by time d esc总结:

CPU报警:很可能是 SQL ⾥⾯有较多的计算导致的
连接数超⾼:很可能是有慢查询,然后导致很多的查询在排队,排查问题的时候可以看到事发现场类似的 SQL 语句⼀⼤⽚,那么有可能是没有索引或者索引不好使,可以⽤:explain 分析⼀下 SQL 语句

4、⼤表怎么优化?某个表有近千万数据,CRUD⽐较慢,如何优化?

出现概率: ★★★

千万级其实数量不⼤, CRUD⽐较慢, 可能要考虑磁盘、索引等问题.

5、垂直分表的适⽤场景和优缺点

出现概率: ★★★

把主码和⼀些列放到⼀个表,然后把主码和另外的列放到另⼀个表中。

如果⼀个表中某些列常⽤,⽽另外⼀些列不常⽤,则可以采⽤垂直分割,另外垂直分割可以使得数据⾏变⼩,⼀个数据⻚就能存放更多的数据,在查询时就会减少I/O次数。其缺点是需要管理冗余列,查询所有数据需要join操作

垂直切分的优点:

解决业务系统层⾯的耦合,业务清晰

与微服务的治理类似,也能对不同业务的数据进⾏分级管理、维护、监控、扩展等

⾼并发场景下,垂直切分⼀定程度的提升IO、数据库连接数、单机硬件资源的瓶颈

缺点:

部分表⽆法join,只能通过接⼝聚合⽅式解决,提升了开发的复杂度

分布式事务处理复杂

依然存在单表数据量过⼤的问题(需要⽔平切分)

6、⽔平分表的适⽤场景和优缺点

出现概率: ★★★
⽔平切分分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同⼀个表按不同的条件分散到多个数据库或多个表中,每个表中只包含⼀部分数据,从⽽使得单个表的数据量变⼩,达到分布式的效果。

⽔平切分的优点:

不存在单库数据量过⼤、⾼并发的性能瓶颈,提升系统稳定性和负载能⼒

应⽤端改造较⼩,不需要拆分业务模块

缺点:

跨分⽚的事务⼀致性难以保证

跨库的join关联查询性能较差

数据多次扩展难度和维护量极⼤

7MySQL的复制原理以及流程

MySQL主从复制⼯作原理

在主库上把数据更⾼记录到⼆进制⽇志

从库将主库的⽇志复制到⾃⼰的中继⽇志

从库读取中继⽇志的事件,将其重放到从库数据中

基本原理流程,3个线程以及之间的关联

主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中;

从:io线程——在使⽤start slave 之后,负责从master上拉取 binlog 内容,放进⾃⼰的relay log中;

从:sql执⾏线程——执⾏relay log中的语句;

复制过程

Binary log:主数据库的⼆进制⽇志

Relay log:从服务器的中继⽇志

第⼀步:master在每个事务更新数据完成之前,将该操作记录串⾏地写⼊到binlog⽂件中。

第⼆步:salve开启⼀个I/O Thread,该线程在master打开⼀个普通连接,主要⼯作是binlog dump process。如果读取的进度已经跟上了master,就进⼊睡眠状态并等待master产⽣新的事件。I/O线程最终的⽬的是将这些事件写⼊到中继⽇志中。

第三步:SQL Thread会读取中继⽇志,并顺序执⾏该⽇志中的SQL事件,从⽽与主数据库中的数据保持⼀致。

8、读写分离有哪些解决⽅案?

读写分离是依赖于主从复制,⽽主从复制⼜是为读写分离服务的。因为主从复制要求slave不能写只能读(如果对slave执⾏写操作,那么show slave status将会呈现SlaveSQLRunning=NO,此时你需要按照前⾯提到的⼿动同步⼀下slave)。

⽅案⼀

使⽤mysql-proxy代理
优点:直接实现读写分离和负载均衡,不⽤修改代码,masterslave⽤⼀样的帐号,mysql官⽅不建议实际⽣产中使⽤缺点:降低性能, 不⽀持事务

⽅案⼆

使⽤AbstractRoutingDataSource+aop+annotationdao层决定数据源。

如果采⽤了mybatis 可以将读写分离放在ORM层,⽐如mybatis可以通过mybatis plugin拦截sql语句,所有的insert/update/delete都访问master库,所有的select都访问salve库,这样对于dao层都是透明。 plugin实现时可以通过注解或者分析语句是读写⽅法来选定主从库。不过这样依然有⼀个问题, 也就是不⽀持事务,所以我们还需要重写⼀下DataSourceTransactionManager read-only的事务扔进读库, 其余的有读有写的扔进写库。

⽅案三

使⽤AbstractRoutingDataSource+aop+annotationservice层决定数据源,可以⽀持事务.

缺点:类内部⽅法通过this.xx()⽅式相互调⽤时,aop不会进⾏拦截,需进⾏特殊处理。

9、数据表损坏的修复⽅式有哪些?

MySQL数据库出现表损坏, 特别是MyISAM表数据很⼤的时候。有三种⽅法,⼀种⽅法使⽤MySQLrepair tablesql语句,另⼀种⽅法是使⽤MySQL提供的myisamchk,,最后⼀种是mysqlcheck命令⾏⼯具。

1)repair table(建议⽅法,对MyISAM引擎表有⽤)

check table tabTest;

如果出现的结果说StatusOK,则不⽤修复,如果有Error,可以⽤:

repair table tabTest;

进⾏修复,修复之后可以在⽤check table命令来进⾏检查。在新版本的phpMyAdmin⾥⾯也可以使⽤check/repair的功能。

2)myisamchk(该⼯具必须运⾏在服务终⽌条件下,对MyISAM引擎表有⽤)。

myisamchk tablename.MYI

进⾏检测。

myisamchk -of tablename.MYI

⽹上说的其它⽅法:

那么修复test表的⽅法为

myisamchk -r -q /var/lib/mysql/db/test.MYI

如果修复全部表,⽤这个命令

myisamchk -r -q /var/lib/mysql/db/*.MYI

3)、运⾏mysqlcheck命令⾏⼯具(该⼯具可以在服务运⾏状态下执⾏)

检查⼀个库中的所有表:

$ mysqlcheck -c users -uroot -p

Enter password:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大先锋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值