mysql性能优化

目录

1.1准备工作

1.1.1慢查询日志

1.1.2修改mysql配置参数 

1.1.3命令行修改慢查询配置

1.1.4慢日志格式

1.1.5查询缓存

1.2常用工具

1.2.1分析工具

1.2.1.1Mysqidumslow

1.2.1.2 mysqlsla

1.2.1.3pt-query-digest

1.2.2 EXPLAIN 执行计划

1.2.2.1. 用法

1.2.2.2 字段类别

1.2.2.3. id

1.2.2.4. select_type

1.2.2.5. table

1.2.2.6. type

1.2.2.7. possible_keys

1.2.2.8. key

1.2.2.9. key_len

1.2.2.10. ref

1.2.2.11. rows

1.2.2.12. filtered

1.2.2.13. extra

1.2.2.14. 小结

1.3. 数据库引擎

1.4. SQL语句优化

1.4.1常用SQL优化建议

1.4.1.1避免 SELECT *

1.4.1.2避免在where子句中使用!=或<>操作符

1.4.1.3尽量避免全表扫描

1.4.1.4用UNION来代替OR

1.4.1.5 like语句避免前置百分号

1.4.1.6避免where子句中使用参数

1.4.1.7避免在where子句中对字段进行表达式操作、函数操作

1.4.1.8. 避免在where 子句中对字段进行函数操作

1.4.1.9. 避免无意义查询

1.4.1.10. 用exists 代替in

1.4.1.11. 尽量使用数字型字段

1.4.1.12. 使用varchar/nvarchar 代替char/nchar

1.4.1.13. 大临时表使用select into 代替create table

1.4.1.14. 临时表先truncate table,然后drop table

1.4.1.15. 存储过程使用SET NOCOUNT ON

1.4.1.16. 避免向客户端返回大数据量

1.4.1.17. 避免在where 子句中对字段进行null 值判断

1.4.2Join语句优化

1.4.2.1. 尽可能减少Join 语句中Nested Loop 的循环总次数

1.4.2.2. 优先优化Nested Loop 的内层循环

1.4.2.3. 保证Join 语句中被驱动表的Join 条件字段已经被索引

1.4.2.4. 不要太吝惜Join Buffer 的设置

1.4.3. GROUP BY 关键字优化

1.4.4. 大数据量的分页优化

1.4.4.1. 从业务逻辑优化

1.4.4.2. 技术优化方法一

1.4.4.3. 技术优化方法二

1.4.5. 优化更须要优化的Query

1.5索引优化

1.5.1索引使用原则

1.5.2索引分类

 1.5.3索引优化口诀

1.6MySQL主从复制

1.7 MySQL读写分离

1.8 数据库切分(Sharding) 

 1.9 性能优化脑图

1.10 性能优化几点建议和原则


1.1准备工作

1.1.1慢查询日志

        当一条查询语句在一定时间内没有返回结果,才会记录到慢查询日志。默认不开启。

查看慢SQL 日志是否启用(on 表示启用):
show variables like 'slow_query_log';
查看执行慢于多少秒的SQL 会记录到日志文件中
show variables like 'long_query_time';
可以使用模糊搜索,查看所有含有query 的变量信息
show variables like '%query%';

1.1.2修改mysql配置参数 

 my.ini(Linux 下文件名为my.cnf),查找到[mysqld]区段,增加日志的配置。
Windows 下路径一般为C:\ProgramData\MySQL\MySQL Server 5.7\my.ini",可以在
启动参数中查看使用的是那个配置文件。
常用的参数详解:

常用的参数详解:

#--是否开启慢查询日志
slow_query_log=1
# --指定保存路径及文件名,默认为数据文件目录,
slow_query_log_file="bxg_mysql_slow.log"
# --指定多少秒返回查询的结果为慢查询
long_query_time=1
# --记录所有没有使用到索引的查询语句
log_queries_not_using_indexes=1
#--记录那些由于查找了多于1000 次而引发的慢查询
min_examined_row_limit=1000
# --记录那些慢的optimize table,analyze table 和alter table 语句
log_slow_admin_statements=1
#--记录由Slave 所产生的慢查询
log_slow_slave_statements=1

datadir=C:/ProgramData/MySQL/MySQL Server 5.7\Data --数据文件目录
注意:修改以下参数,需要重新启动数据库服务才会生效

1.1.3命令行修改慢查询配置

命令行修改配置方式不需要不重启即可生效,但重启之后会自动失效。

set global slow_query_log=1;
set global slow_query_log_file='bxg_mysql_slow.log';
set long_query_time=1;
set global log_queries_not_using_indexes=1;
set global min_examined_row_limit=1000;
set global log_slow_admin_statements=1;
set global log_slow_slave_statements=1;


其他参数可通过以下命令查阅:

show variables like '%query%';
show variables like '%slow%';

1.1.4慢日志格式

时间、主机信息、执行信息、执行时间、执行内容

1.1.5查询缓存

       Query Cache 会缓存select 查询,安装时默认是开启的,但是如果对表进行INSERT,
UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE, or DROP DATABASE 等操作
时,之前的缓存会无效并且删除。这样一定程度上也会影响我们数据库的性能。所以对一些频繁的变动表的情况开启缓存是不明智的。我们测试数据库性能的时候也要关闭缓存,避免缓存对我们测试数据的影响。

show VARIABLES like '%cache%';

查看缓存命中情况 

select count(*) FROM test;
select count(*) FROM test;
show status like '%qcache%';

 关闭缓存有两种放法,一种临时的,一种永久的。临时的直接在命令行执行

set global query_cache_size=0;
set global query_cache_type=0; --如果配置文件中为关闭缓存的话,不能通过命令开启缓存

永久的修改配置文件my.cnf ,添加下面的配置即可。

query_cache_type=0
query_cache_size=0

另外,我们还可以通过sql_no_cache 关键字在sql 语句中直接禁用缓存,在开启缓存
的情况下我们对sql 语句做一些改动

Select sql_no_cache count(*) from pythonlearn.lianjia; -- 不缓存
Select sql_cache count(*) from pythonlearn.lianjia; -- 缓存(也可以不加,默认缓存已经开启了)

1.2常用工具

1.2.1分析工具

1.2.1.1Mysqidumslow

        mysqldumpslow 是mysql 自带的用来分析慢查询的工具,基于perl 开发。
Windows 下需要下载安装perl 编译器

perl mysqldumpslow.pl --help
perl mysqldumpslow.pl -r -s c -a -t 3 "C:\ProgramData\MySQL\MySQL Server
5.7\Data\bxg_mysql_slow.log"

Count: 4(执行了多少次)
Time=375.01s(每次执行的时间) (1500s)(一共执行了多少时间)
Lock=0.00s (0s)(等待锁的时间)
Rows=10200.3(每次返回的记录数) (40801)(总共返回的记录
数), username[password]@[10.194.172.41]

1.2.1.2 mysqlsla

      Mysqlsla 是daniel-nichter 用perl 写的一个脚本,专门用于处理分析Mysql 的日志而存在。通过Mysql 的日志主要分为:General log,slow log,binary log 三种。通过query 日志,我们可以分析业务的逻辑,业务特点。通过slow log,我们可以找到服务器的瓶颈。通过binary log,我们可以恢复数据。Mysqlsla 可以处理其中的任意日志。MySQL日志分析神器之mysqlsla-阿里云开发者社区

1.2.1.3pt-query-digest

        pt-query-digest 是用于分析mysql 慢查询的一个工具,它可以分析binlog、General
 、log、slowlog,也可以通过SHOWPROCESSLIST 或者通过tcpdump 抓取的MySQL 协议数据来进行分析。可以把分析结果输出到文件中,分析过程是先对查询语句的条件进行参数化,然后对参数化以后的查询进行分组统计,统计出各查询的执行时间、次数、占比等,可以借助分析结果找出问题进行优化。参考:https://blog.csdn.net/seteor/article/details/24017913

1.2.2 EXPLAIN 执行计划

1.2.2.1. 用法

1. EXPLAIN SELECT ……
经常使用的方式,查看sql 的执行计划
2. EXPLAIN EXTENDED SELECT ……
将执行计划"反编译"成SELECT 语句,运行SHOW WARNINGS ,可得到被MySQL
优化器优化后的查询语句。
3. EXPLAIN PARTITIONS SELECT ……
用于分区表的EXPLAIN 生成QEP 的信息,用来查看索引是否正在被使用,并且输出
其使用的索引的信息。


1.2.2.2 字段类别

1.2.2.3. id

        包含一组数字,表示查询中执行select 子句或操作表的顺序,id 相同执行顺序由上至
下。如果是子查询,id 的序号会递增,id 值越大优先级越高,越先被执行。

1.2.2.4. select_type

所使用的SELECT 查询类型,包括以下常见类型:
a. SIMPLE:表示为简单的SELECT,查询中不包含子查询或者UNION
b. PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
c. SUBQUERY : 在SELECT 或WHERE 列表中包含了子查询, 该子查询被标记为
SUBQUERY
d. UNION:表连接中的第二个或后面的select 语句,若第二个SELECT 出现在UNION
之后,则被标记为UNION。
e. DERIVED:DERIVED(衍生)用来表示包含在from 子句中的子查询的select。若
UNION 包含在FROM 子句的子查询中,外层SELECT 将被标记为DERIVED。mysql 会递归执行并将结果放到一个临时表中。服务器内部称为"派生表",因为该临时表是从子查询
中派生出来的
f.UNION RESULT:从UNION 表获取结果的SELECT 被标记为UNION RESULT
g.DEPENDENT:意味着select 依赖于外层查询中发现的数据。
h.UNCACHEABLE:意味着select 中的某些特性阻止结果被缓存于一个item_cache
中。

1.2.2.5. table

所使用的的数据表的名字,他们按被读取的先后顺序排列。

1.2.2.6. type

表示MySQL 在表中找到所需行的方式, 又称“ 访问类型” 。取值按优劣排序为NULL>system > const > eq_ref > ref > fulltext > ref_or_null > index_merge >unique_subquery > index_subquery > range > index > ALL。一般来说,得保证查询至少达到range 级别,最好能达到ref。
a.ALL:Full Table Scan 全表扫描,MySQL 将遍历全表以找到匹配的行。

b.index:Full Index Scan 全索引扫描,index 与ALL 区别为index 类型只遍历索引树

c. range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行。显而易见的索引范围扫描是带有between 或者where 子句里带有<, >查询。当mysql 使用索引去查找一系列值时,例如IN()和OR 列表,也会显示range(范围扫描),当然性能上面是有差异的。
d. ref_or_null:该联接类型如同ref,但是添加了MySQL 可以专门搜索包含NULL 值的行。
e. index_merge:该联接类型表示使用了索引合并优化方法。
f. unique_subquery: 该类型替换了下面形式的IN 子查询的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) 。unique_subquery 是一个索引查找函数,可以完全替换子查询,效率更高。
g. index_subquery:该联接类型类似于unique_subquery。可以替换IN 子查询,但只适合下列形式的子查询中的非唯一索引: value IN (SELECT key_column FROMsingle_table WHERE some_expr)
h.ref:就是连接程序无法根据键值只取得一条记录,使用索引的最左前缀或者索引不是primary key 或unique 索引的情况。当根据键值只查询到少数几条匹配的记录时,这就是一个不错的连接类型。
i.eq_ref:类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key 或者unique key 作为关联条件.
j.const、system:当MySQL 对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where 列表中,MySQL 就能将该查询转换为一个常量。
注:system 是const 类型的特例,当查询的表只有一行的情况下,使用system
k.NULL:MySQL 在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
explain select * from address where id = (select min(id) from person);

1.2.2.7. possible_keys

指出MySQL 能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用

1.2.2.8. key

显示MySQL 在查询中实际使用的索引,若没有使用索引,显示为NULL

1.2.2.9. key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len 显示
的值为索引字段的最大可能长度,并非实际使用长度。如果键是NULL,则长度为NULL。


1.2.2.10. ref

显示索引的哪一列被使用了,有时候会是一个常量:表示哪些列或常量被用于用于查
找索引列上的值,可能值为库.表.字段、常量、null。


1.2.2.11. rows

MySQL 根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。

1.2.2.12. filtered

显示了通过条件过滤出的行数的百分比估计值。

1.2.2.13. extra

包含不适合在其他列中显示但十分重要的额外信息,提供了与关联操作有关的信息,
没有则什么都不写。
a.Using index:该值表示相应的select 操作中使用了覆盖索引(Covering Index)。
MySQL 可以利用索引返回select 列表中的字段,而不必根据索引再次读取数据文件包含
所有满足查询需要的数据的索引称为覆盖索引(Covering Index)。注意:如果要使用覆
盖索引,一定要注意select 列表中只取出需要的列,不可select *,因为如果将所有字段
一起做索引会导致索引文件过大,查询性能下降。
b.Using where:表示mysql 服务器将在存储引擎检索行后再进行过滤。许多where
条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是
所有带where 字句的查询都会显示"Using where"。有时"Using where"的出现就是一个暗
示:查询可受益与不同的索引。
c.Using temporary:表示MySQL 需要使用临时表来存储结果集,常见于排序和分组
查询。这个值表示使用了内部临时(基于内存的)表。一个查询可能用到多个临时表。有很
多原因都会导致MySQL 在执行查询期间创建临时表。两个常见的原因是在来自不同表的
上使用了DISTINCT,或者使用了不同的ORDER BY 和GROUP BY 列。可以强制指定一个
临时表使用基于磁盘的MyISAM 存储引擎。这样做的原因主要有两个:1)内部临时表占用
的空间超过min(tmp_table_size , max_heap_table_size) 系统变量的限制; 2) 使用了
TEXT/BLOB 列。
d. Using filesort:MySQL 中无法利用索引完成的排序操作称为“文件排序”
e. Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓
冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添
加索引来改进能。
f. Impossible where:这个值强调了where 语句会导致没有符合条件的行。
h. Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚
合函数结果中返回一行.
I. Index merges:当MySQL 决定要在一个给定的表上使用超过一个索引的时候,就
会出现以下格式中的一个,详细说明使用的索引以及合并的类型。
Using sort_union(...)
Using union(...)
Using intersect(...)

1.2.2.14. 小结

• EXPLAIN 不考虑各种Cache
• EXPLAIN 不能显示MySQL 在执行查询时所作的优化工作
• 部分统计信息是估算的,并非精确值
• EXPALIN 只能解释SELECT 操作,其他操作要重写为SELECT 后查看执行计划。
• EXPLAIN 不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响
情况

1.3. 数据库引擎

InnoDB

InnoDB是一个事务型的存储引擎

锁的粒度更小,锁定在行级,写操作不会锁定全表

InnoDB也支持FOREIGN KEY强制

可以从灾难中恢复(通过bin-log日志等)

MyIsam

ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源。

在设计之初就预想数据组织成有固定长度的记录,按顺序存储的。ISAM是一种静态索引结构。

表级锁

不支持事务

           也不能够容错

1.4. SQL语句优化

1.4.1常用SQL优化建议
1.4.1.1避免 SELECT *

从数据库里读出越多的数据,那么查询就会变得越慢。并且如果你的数据库服务器和
WEB 服务器是两台独立的服务器的话,这还会增加网络传输的负载。
select * from person where lname='x8RJWmQX';
select id from person where lname='x8RJWmQX';

1.4.1.2避免在where子句中使用!=或<>操作符

应尽量避免在where 子句中使用!=或<>操作符,否则引擎放弃使用索引而进行全表扫描。
EXPLAIN select * from person where fname != 'sss’ ;

1.4.1.3尽量避免全表扫描

对查询进行优化,应尽量避免全表扫描,首先应考虑在where 及order by 涉及的列上建立索引。

1.4.1.4用UNION来代替OR

采用OR 语句:
select * from person where fname ='LVc1oJjd' or fname='bjRdlVo';
采用UNION 语句,返回的结果同上面的一样,但是速度要快些:
select * from person where fname ='LVc1oJjd'
Union select * from person where fname='bjRdlVo';

我们来比较下重要指标,发现主要差别是type 和ref 这两项。type 显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge >unique_subquery > index_subquery > range > index > ALL,UNION 语句的type 值为一般为ref,OR 语句的type 值为range,可以看到这是一个很明显的差距。UNION 语句的ref 值为const,OR 语句的type 值为null,const 表示是常量值引用,非常快。这两项的差距就说明了UNION 要优于OR,从我们的直观感觉上也可以理解,虽然这两个方式都用到了索引,但UNION 是用一个明确的值到索引中查找,目标非常明确,OR 需要对比两个值,目标相对要模糊一些,所以OR 在恍惚中落后了。

1.4.1.5 like语句避免前置百分号

前置百分号会导致索引失效
select * from person where fname like '%LVc1o%' ;

1.4.1.6避免where子句中使用参数

        如果在where 子句中使用参数,也会导致全表扫描。因为SQL 只有在运行时才会解
析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。
然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入
项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num

1.4.1.7避免在where子句中对字段进行表达式操作、函数操作

应尽量避免在where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2

1.4.1.8. 避免在where 子句中对字段进行函数操作

应尽量避免在where 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)=’abc’ –name 以abc 开头的id
select id from t where datediff(day,createdate,’ 2005-11-30′)=0 –’2005-11-30′生成
的id
应改为:
select id from t where name like ‘abc%’
select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′

1.4.1.9. 避免无意义查询

不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(…)

1.4.1.10. 用exists 代替in

很多时候用exists 代替in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)

1.4.1.11. 尽量使用数字型字段

尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询
和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符
串中每一个字符,而对于数字型而言只需要比较一次就够了。

1.4.1.12. 使用varchar/nvarchar 代替char/nchar

尽可能的使用varchar/nvarchar 代替char/nchar ,因为首先变长字段存储空间小,
可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

1.4.1.13. 大临时表使用select into 代替create table

在新建临时表时, 如果一次性插入数据量很大, 那么可以使用select into 代替
create table,避免造成大量log ,以提高速度;如果数据量不大,为了缓和系统表的资
源,应先create table,然后insert。

1.4.1.14. 临时表先truncate table,然后drop table

如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate
table ,然后drop table ,这样可以避免系统表的较长时间锁定。

1.4.1.15. 存储过程使用SET NOCOUNT ON

在所有的存储过程和触发器的开始处设置SET NOCOUNT ON ,在结束时设置SET
NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送
DONEINPROC 消息。

1.4.1.16. 避免向客户端返回大数据量

尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

1.4.1.17. 避免在where 子句中对字段进行null 值判断

应尽量避免在where 子句中对字段进行null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num is null
可以在num 上设置默认值0,确保表中num 列没有null 值,然后这样查询:
select id from t where num=0
在Mysql5.7 版本中该条建议已经不用考虑了,因为null 判断也能使用索引了。

1.4.2Join语句优化
1.4.2.1. 尽可能减少Join 语句中Nested Loop 的循环总次数

最有效的办法是让驱动表的结果集尽可能地小,“永远用小结果集驱动大结果集”。
比如,当两个表(表A 和表B)Join 时,如果表A 通过WHERE 条件过滤后有10 条
记录,而表B 有20 条记录。如果选择表A 作为驱动表,也就是被驱动表的结果集为20,
那么我们通过Join 条件对被驱动表(表B)的比较过滤就会进行10 次。反之,如果选择
表B 作为驱动表,则须要进行20 次对表A 的比较过滤。

1.4.2.2. 优先优化Nested Loop 的内层循环

不仅在数据库的Join 中应该这样做,实际上在优化程序语言时也有类似的优化原则。
内层循环是循环中执行次数最多的,每次循环节约很少的资源,就能在整个循环中节约很
多的资源

1.4.2.3. 保证Join 语句中被驱动表的Join 条件字段已经被索引

其目的正是基于上面两点的考虑,只有让被驱动表的Join 条件字段被索引了,才能保
证循环中每次查询都能够消耗较少的资源,这也正是内层循环的实际优化方法

1.4.2.4. 不要太吝惜Join Buffer 的设置

当无法保证被驱动表的Join 条件字段被索引且内存资源充足时, 不要太吝惜Join
Buffer 的设置。在Join 是All、Index、range 或index_merge 类型的特殊情况下,Join Buffer
才能派上用场。在这种情况下,Join Buffer 的大小将对整个Join 语句的消耗起到非常关键
的作用

1.4.3. GROUP BY 关键字优化

1、group by 实质是先排序后分组,遵照索引的最佳左前缀。
2 、当无法使用索引列, 增大max_length_for_sort_data 参数的设置+ 增大sort_buffer_size 参数的设置
3、where 高于having,能写在where 限定的条件就不要去having 去限定了。

1.4.4. 大数据量的分页优化

使用limit 进行分页,翻到10000 多页后效率低。原因在于limit offset 会逐行查找,
是先查询再跳过。
select * from person limit 999900,100; -- 慢了,大概需要0.4 秒多

1.4.4.1. 从业务逻辑优化

不允许翻过100 页,例如百度一般可以翻到70 页左右

1.4.4.2. 技术优化方法一

select * from person where id>999900 limit 100;
这样就非常快,0.001s 左右,因为使用了id 索引
但这样用有前提,id 是连续的,中间的数据不能删,否则id 为999900 的并不是第
999900 个记录。

1.4.4.3. 技术优化方法二

如果必须用limit offset 查询,就用延迟关联
select id from person limit 999900 ,100;
这样只查询id 列,实现了索引覆盖,就会很快
select p.* from person p inner join (select id from person limit 999900 ,100) as tmp on p.id=tmp.id;
通过内连接再获取分页后每条记录的详细信息

1.4.5. 优化更须要优化的Query

这个问题须要从对整个系统的影响来考虑。哪个Query 的优化能给系统整体带来更大
的收益,就更须要优化。一般来说,高并发低消耗的影响> 低并发高消耗
假设有一个Query 每小时执行10000 次,每次需要20 个IO,而另外一个Query 每
小时执行10 次,每次需要20000 个IO。
(1)通过IO 消耗来分析
两个Query 每小时所消耗的IO 总数目是一样的,都是200000 IO/小时
假设优化第一个Query,从20 个IO 降低到18 个IO,也就是降低了2 个IO,则节
省了2×10000 = 20000 (IO/小时)
而如果希望通过优化第二个Query 达到相同的效果,必须要让每个Query 减少20000
/ 10 = 2000 IO
可以看出第一个Query 节省2 个IO 即可达到第二个Query 节省2000 个IO 相同的
效果
(2)通过CPU 消耗来分析
原理和上面一样,只要让第一个Query 节省一小块资源,就可以让整个系统节省出一
大块资源,尤其是在排序、分组这些对CPU 消耗比较多的操作中更加明显
(3)从对整个系统的影响来分析
一个频繁执行的高并发Query 的危险性比一个低并发的Query 要大很多,当一个低
并发的Query 执行计划有误时,所带来的影响只是该Query 请求者的体验会变差,对整
体系统的影响并不会特别突出,但是,如果一个高并发的Query 执行计划有误,它带来的
后果很可能就是灾难性的。

1.5索引优化

1.5.1索引使用原则

并不是所有索引对查询都有效

索引并不是越多越好

数据量小的表最好不要使用索引

避免在不同值少的列上加索引

根据业务需求建立索引

1.5.2索引分类

普通索引

唯一索引

主键索引

组合索引

 1.5.3索引优化口诀

全值匹配我最爱,最左前缀要遵守;

带头大哥不能死,中间兄弟不能断;

索引列上少计算,范围之后全失效;

Like百分写最右,覆盖索引不写星;

不等空值还有or,索引失效要少用;

VAR引号不可丢,SQL高级也不难!

1.6MySQL主从复制

Master配置

启用二进制日志

指定serverid

创建授权用户

查看当前二进制日志文件名,及最新位置。

Slave配置

启用二进制日志

指定serverid

配置被授权用户信息、日志文件及位置信息,指向master

启动slave的命令

1.7 MySQL读写分离

MaxScale安装

Master创建用户

创建监控用户

创建路由用户

MaxScale配置

配置maxscale.cnf

启动MaxScale

MaxScale测试

1.8 数据库切分(Sharding 

数据的垂直切分

依照不同的表来切分到不同的数据库(主机)之上

一般按照业务逻辑划分

数据的水平切分

依据表中的数据的逻辑关系,将同一个表中的数据依照某种条件拆分到多台数据库(主机)上面

简单的水平切分主要是表依照某个字段的某种规则来分散到多个表之中

 联合切分

既有垂直切分
也有水平切分

 1.9 性能优化脑图

 

1.10 性能优化几点建议和原则

1、适度优化,切忌过度优化

2、先优化最大瓶颈,事半功倍

3、依据数据而不是凭空猜测

4、性能优化是持久战,道高一尺魔高一丈

5、深入理解业务

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MySQL性能优化是提升数据库查询和操作效率的关键步骤。以下是一些常见的MySQL性能优化技巧: 1. 使用合适的索引:在经常用于查询的列上创建索引,可以大大提高查询性能。避免创建过多的索引,因为过多的索引可能会导致性能下降。 2. 优化查询语句:编写高效的查询语句是提升性能的关键。避免全表扫描,尽量使用索引来加速查询。使用EXPLAIN命令来分析查询计划,检查是否存在慢查询。 3. 适当分区:对于大型表,可以根据数据的特点将其分成多个分区,以提高查询和维护性能。 4. 调整缓冲区大小:适当调整MySQL的缓冲区大小,如innodb_buffer_pool_size和key_buffer_size,以提高读写性能。 5. 合理配置服务器参数:调整MySQL服务器的参数,如max_connections、innodb_buffer_pool_instances等,以适应实际需求并提高性能。 6. 避免过度规范化:过度规范化可能导致频繁的表连接操作,降低性能。根据实际情况进行适当的冗余设计,以减少表连接操作。 7. 使用批量插入和更新:使用批量插入和更新语句,如INSERT INTO ... VALUES(...), (...), ...,可以减少客户端和服务器之间的通信次数,提高性能。 8. 定期维护和优化表:定期进行表优化、碎片整理、统计信息更新等数据库维护操作,以提高性能。 这些是一些常见的MySQL性能优化技巧,根据具体场景和需求,还可以进行其他优化措施。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

悠哉iky

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

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

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

打赏作者

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

抵扣说明:

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

余额充值