Mysql 性能优化

Mysql优化方案

 

1、mysql的优化点

a、sql语句优化

b、索引优化

c、数据库结构优化

d、理解查询执行计划[即EXPLAIN分析sql语句后的结果集分析]

e、缓冲与缓存[缓存,如果是更新不频繁的系统,建议开启;但如果是更新频繁的系统建议关闭]

f、锁优化[用innodb自己的锁机制,不用自己操作锁,但我们可以查看锁]

g、mysql服务器优化

2、关于sql语句

2.1、冗余

优点:在sql查询过程中,如果能做字段冗余的,尽量做好冗余,这样能够避免表的join;

缺点:就是每次更新的时候需要更改相应做冗余的地方。

总的来说:更新操作通常是比较快,多这一步操作,带来的是性能飙升,完全值得。

2.2、适当地分步查询

原因:sql查询语句,一条sql语句只能交给一个cpu处理,如果过多的join与子查询,将严重影响性能,如果我们采用分步骤的进行,sql语句就可以交给多个cpu处理。

注意:有时候分步太多,也不一定会起到提高性能的作用,有些反而降低了性能,所以需要衡量,选择合适的方案。

eg:这是我做过的例子

但是有时候确实没有比join更好的方式,那就join吧。

2.3、减少全表扫描

LIKE:尽量减少这种模糊查询,如果数据量少倒还行,数据量一大,就严重超过用户的忍耐度。如果场景里不可避免,可以考虑就用搜索引擎技术,开源的有基于lucene的solr、elasticsearch等技术。

IS NULL做WHERE的条件:设置表的时候设置为。

OR:会导致引擎放弃索引,进行我全表扫描,如select id from t where num=10 or num=20可以这样查询:select id from t where num=10 union all select id from t where num=20。

WHERE子句中使用参数:如select id from t where num=@num,如果要用改为强制索引查询select id from t with(index(索引名)) where num=@num。

WHER子句中表达式操作:如select id from t where num/2=100,就改为select id from t where num=100*2。

WHERE子句中对字段进行函数操作:这将导致引擎放弃使用索引而进行全表扫描。

count(*):可以用count(1)代替。

select(*):使用什么字段,就写什么字段。

ORDER BY:order by语句的字段设置成索引。

3、关于索引

3.1、innodb存储引擎常见索引

B+树索引、hash索引、全文索引

3.2、b+树索引

1、b+树索引并不能一下找到给定值的具体行,而是只能找到具体数据所在的页,然后数据库把页读入内存,在内存中进行查找,得到所需数据。

2、分类

聚集索引、辅助索引

3.2.1、聚集索引

含义:主键或者唯一键[没有主键有唯一键的表]或者RowID[没有主键也没有唯一键,系统默认]来构建一个b+树,叶子存放表的行数据,叶子也叫数据叶,这样的结构决定了数据也是索引的一部份,访问索引就很容易找到索引上的数据。

3.2.2、辅助索引

含义:除了聚集索引外的所有索引都被称为辅助索引,对于辅助索引,叶子节点不包含行记录的全部数据。

原理:辅助索引->找到叶子节点->节点中获取主键->主键再去聚集索引上获取行数据[包含了两次对b+树查找过程]。

3.2.3、索引管理

创建:CREATE INDEX | KEY idx_b ON t竖线是或者之意

ALTER TABLE t ADD INDEX | KEY idx_b (b(100));//前缀索引

ALTER TABLE t ADD INDEX | KEY idx_a_b (a,b);//联合索引

删除:ALTER TABLE t DROP INDEX | KEY idx_b;

DROP INDEX idx_b ON T;

查看:SHOW INDEX FROM t

 

 

3.2.4、b+树索引的使用

1、前缀索引:对于字符串,要在它上边建立索引,如果字符过长,会使索引变得过大,查询效率变差,占用过多的存储空间。但如果我们选择字符的前边一部份做成索引,那么就大幅节省了索引空间,提高索引的效率。

1)、前缀索引选择策略:

 

 

1)、优点:因为b+树中,所有键值都是有排序的,所以联合起来,筛选的效率就变得很高。

2)、注意:没有排序或分组时把选择性高的放在前面,效果会更好。

3)、选择性衡量策略:

 

 

哪个值更接近1,选择性就高。

3、覆盖索引:InnoDB支持覆盖索引(覆盖索引并非是一种可以通过SQL语句创建的索引,与前缀索引、联合索引不同,我们可以认为这是一种逻辑上的索引,即符合一定条件的索引我们都可以称之为是覆盖索引),即从辅助索引中就可以直接得到查询的记录,而不需要再次查询聚集索引中的记录。使用覆盖索引的一个好处就是辅助索引不包含整行记录,因此它的大小远小于聚集索引,可以减少大量IO操作,查询速度很快。

不是所有的索引都能够成为覆盖索引,覆盖索引必须要存储索引列的值。当我们发起一个一个被索引覆盖的查询时,在EXPLAIN的Extra列可以看到Using Index信息,表示该次查询在索引上就直接获得了所有需要的数据,也即这是一个覆盖索引。如下图所示:

 

 

 

由于cid与uid同时存在于索引中,因此当查询cid与uid时,就可以直接从辅助索引中可以获取所需的字段,而不需要再次去查找聚集索引。

3.3、哈希索引

1、哈希索引是一种key-value形式的结构,故检索起来很快。

2、InnoDB存储引擎支持的哈希索引是自适应的,即InnoDB会根据表的使用情况自动为表生成哈希索引,不能人为地干预在一张表中生成哈希索引。

3.4、全文索引

Mysql-5.7.6内置了ngram全文检索插件,根据ngram_token_size的大小来对中文进行分词,ngram_token_size的值范围[1-10],size越大,索引的体积就越大,默认为2。

所谓全文索引就是将一句话分成多个词语,建成索引,进行搜索。

3.5、索引是否用到分析

1、用QEP[查询执行计划]进行分析,也即用EXPLAIN分析SQL语句。

 

 

只需要观察type,key,Extra字段,就可以看设置的索引有没有被用到

3、type值代表索引的性能,性能高低排序

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

extra如果有Using filesort或者Using temporary的话,就必须要优化了

4、数据库结构优化

1、需求分析,充分吃透需求,反复推演逻辑关系,制成合理的UI图,表结构。

2、当前WEB的使用场景,基本上是查多写少,对于多张表存在逻辑关系,采用反范式设计,增加字段冗余,减少多表联合,提高查询性能。

3、采用数据库、表及字段的命名规范[可读性原则、表意性原则、长名原则]。

4、为字段选择合适的数据类型

a、对于数字类型

整型:tinyint(一个字节)、smallint(2个字节)、mediumint(3个字节)、int(4个字节)、bigint(8个字节)

实数:flout(4字节,不为精确类型)、double(8字节,不为精确类型)、decimal(每4个字节存9个数字,小数点占一个字节,为精确类型)

b、对于字符串类型

char类型:特点[类型定长、删除末尾空格、存储最大宽度255];适用场景[适合存储长度近似的值(md5、电话号码、身份证号等有固定长度的值)、适合存长度短小的字符串、适合存储经常更新的字符串]。

varchar类型:特点[用于存储长度变长的字符串、列小于255要占用一个额外字节用于存储字符串长度、列大于255要占用两个字节用于存储字符串长度];原则[选用合适的长度,不同的长度性能不一样];适用场景[字符串的最大长度比平均长度在很多、字符串的列很少被更新、使用多字符集存储字符串]。

c、日期类型

datatime类型以YYYY-MM-DD HH:MM:SS[.fraction]格式存储数据datatime类型与时区无关,占用8个字节存储空间 存储的时间范围:1000-01-01 00:00:00到9999-12-31 23:59:59

timestamp类型存储从1970年1月1日到当前的秒数,以YYYY-MM-DD HH:MM:SS[.fraction]显示,占用4个字节存储空间timestamp类型显示依赖于所指定的时区timestamp类型在行数据修改时可以自动修改timestamp列的值timestamp存储的时间范围1970-01-01到2038-01-19

date类型和time类型(mysql5.7之后加入):date类型占用的字节数比使用字符串、datatime、int存储要少,使用date类型只需要3个字节;date类型使用Date类型还可以利用日期时间函数进行日期之间的计算;date类型存储的日期范围1000-01-01到9999-12-31之间的日期

time类型用于存储时间数据:HH:MM:SS存储日期时间类型的注意事项:不要使用字符串类型来存储日期时间数据;日期时间类型通常比字符串类型所占用的存储空间小;日期时间类型在进行查找过滤时可以利用日期来进行对比;日期时间类型有丰富的处理函数,可以方便的对时间类型的进行日期计算

使用Int存储日期时间不如使用Timestamp类型

5、mysql服务器优化

5.1、选取合适的硬件系统

比如主高频CPU、多核CPU、SSD硬盘、PCIE卡、合适的带宽

5.2、合理的系统参数配置

1.开启慢查询日志slow_query_log=on

2.查询慢查询的时间标准long_query_time,建议设置小于3秒

3.慢查询日志的存储位置slow_query_log_file

4.缓冲池设置innodb_buffer_pool_size为物理内存的50%~70%

5.innodb_log_file_size,5.5以上设置为1G以上,5.5以下不要超过512M

6.innodb_flush_log_at_trx_commit, 0最快数据最不安全1.最慢最安全2折中

7.innodb_max_dirty_pages_pct,25%~50%为宜

8.innodb_io_capacity,普通硬盘1000左右SSD10000左右PCleSSD20000左右

9.sync_binlog 0最快数据最不安全,系统自己决定刷新binlog的频率;1最慢最安全,每个event刷新一次binlog;N每N个事务刷新一次binlog

10.open_files_limit & innodb_open_files,建议65535

11.max_connections,突发最大连接数的80%为宜,过大容易全部卡死

12.thread_handling =”pool-of-thread”,启用线程池,好像企业版才支持

13.query_cache_size & query_cache_type҅,缓存,如果是更新不频繁的系统,建议开启;但如果是更新频繁的系统建议关闭。

 

如何发现sql语句问题在哪?
1. 开启慢查询,使用慢日志查询比较慢的sql语句

2. explain分析查询语句的效率

1. select_type查询类型,大部分有效率的语句类型都是simple

2. system理论上是最快的,只用了主键,全表只有一行

3. const在实际上是快的,使用了主键索引,返回一行

 

3. 三大范式,行不可分。列不可分,表不可分

细解:

第一范式:表的列具有原子性不可分解

第二范式:每张表只表达一个意思,表的每个字段都和主键有依赖关系

第三范式:每张表除了主键外的所有字段都只能和主键有依赖关系,不能过多依赖

 

4. 反三大范式

没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据

做法:设计时遵守三大范式,物理数据模型设计,就是增加字段,减少查询时的关联,提高查询效率

 

5. 合理的选择数据类型

比如

姓名:char(20)

价格:decimal(7,3)

文章内容:text

Md5:char(32)

Ip:char(15)

Email:char(32)

1. 选择合理范围内最小的数据类型,可以减少磁盘空间,以及I/0读写开销,减少内存,cpu占用率

2. 选择最相对简单的数据类型

3. 不要使用null,因为mysql对null字段索引优化不佳,增加计算难度,在保存和处理上也要做更多的工作,当然有些值如果没有值得时候给默认0就可以

4. 数值类型的选择,数值类型的比字符串占用空间小,处理速度快

 

 

6. sql语句优化

1. 给每张表加索引,可以提高查询效率的查询

 

索引类型:

1. 主键,运行速度最快,每张表只有一个,建议每张表都建立一个主键,该主键就是id

2. 唯一索引:速度仅次于主键,一张表可以有多个

3. 普通索引:最慢,几乎没有限制

4. 全文索引:主要用于模糊搜索,表的类型必须是myisam,涉及字段必须是字符串

 

 

7. 查询优化

1. 任何sql语句的where条件,都必须涉及到索引,最好是主键其次是唯一

2. 尽量避免关联查询

3. 复杂的语句,分开简单写

4. 涉及到groupby,orderby字段必须设置索引

 

 

8. 其他优化

1. 尽量不要使用rand(),curdata()系统自带函数,sql不会缓存

2. 行数过多的尽量使用limit限制

3. 避免使用select*

4. 不要使用永久链接

 

 

9. 服务器硬件优化

1. mysql对cpu核数的支持不是越多越快

2. Mysql5.5使用的服务器不要超过32核

 

 

10. 引擎优化

1. myisam分为静态,动态,压缩  不支持事物

2. Innodb支持事物,行级锁机制,外键约束的功能

3. Merge用于日志和数据仓库

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值