代码改变世界

Mysql性能调优

2017-06-10 22:26  fengna  阅读(367)  评论(0编辑  收藏  举报

1. 宏观上调优可以考虑三个部分,分别为硬件、网络、软件,此处主要考虑软件调优

(1)软件调优包括:表设计(范式、字段类型、数据存储引擎)、SQL语句语索引、配置文件参数、文件系统、操作系统、MYSQL版本、体系架构

2. 表设计

(1) 第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本数据类型构成,包括整型、字符型、逻辑型、日期型等。(只要是关系型数据库都符合第一范式)

(2) 第二范式(2NF):要求实体的属性完全依赖于主关键字,即只能有一个主关键字。也即非关键字段都依赖于主键

(3) 第三范式(3NF):不存在非关键字段对任一候选关键字段的传递函数依赖。

3. 字段类型的选择:一般原则是保小不保大,能用占字节少的字段就不用大字段。

3.1 数值类型

(1)录入手机号码用bigint

(2)IP地址可以采用unsigned int整型,并采用INET_NTOA()负责将数字转换为IP地址,INET_ATON()负责将IP地址转换为数字

(3)根据需要选择最小整数类型

3.2 字符类型

(1)计算varchar的最大长度:varchar(32766)

3.3 时间类型

4. 采用更合适的锁机制

4.1 MYSQL的锁分为三种:

(1)表级锁:开销小、加锁快,不会出现死锁;锁粒度大,发生冲突的概率最高,并发度最低。MyISAM引擎

(2)行级锁:开销大、加锁慢、会出现死锁;锁粒度最小,发生冲突的概率最低,并发度最高。InnoDB引擎

(3)页面锁:介于中间。NDB引擎

4.2 MyISAM引擎:

(1)对MyiSAM表的读操作(加读锁),其它进程可以读,但是会阻塞同一表的写操作;

(2)对MyISAM表的写操作,会阻塞其它线程对同一表的读写操作,只有当写锁释放后,才会执行其它进程的读写操作;

4.3 InnoDB引擎:InnoDB存储引擎是通过给索引上的索引项加锁来实现的,这说明只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将采用表锁 (为防止在高并发访问下,大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重的性能问题,这时可以通过设置合适的锁等待超时阈值参数innode_lock_wait_timeout来解决,一般设置为100s)

5 选择合适的事务隔离级别

5.1 事务的属性:

(1)原子性

(2)一致性

(3)隔离性

(4)持久性

5.2 不确定的读取情况

(1)脏读:一个事务开始读取某行数据,另外一个事务已经更新了此数据但没有及时提交。而另一事务可能发生回滚。

(2)不可重复读:一个事务对同一行数据重复读取两次,但是得到了不同的结果。例如,在两次读取的途中,有另外一个事务对该行的数据进行了修改并提交。

(3)两次更新问题:无法重复读取的特例。两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就造成第一次写操作失效

(4)幻读:事务在操作过程中进行了两次查询,第二次查询的结果包含了第一次查询中未出现的数据。这是因为在两次查询过程中有另外一个事务插入数据。

5.3 InnodDB 事务隔离级别

(1)Read Uncommitted 读未提交:会产生脏读取。(“排他写锁”)

(2)Read Committed 读提交:会产生不可重复读取。(“瞬间共享读锁”和“排他写锁”)

(3)Repeated Read 可重复读取:会产生幻读。(“共享读锁”和“排他写锁”)

(4)Serilizable 序列化:提供严格的事务隔离,事务严格序列化,事务只能一个接一个地执行,不能并发执行。

 6. SQL优化与合理利用索引

6.1 通过开启慢日志来定位执行很慢的SQL语句:(explain优化器查询)

开启慢日志的方法:在my.cnf配置文件中,加入以下参数:

slow_query_log=1

slow_query_log_file=mysql.slow

long_query_time=2(超过2秒的SQL会记录下来)

6.2 SQL优化案例分析

(1)not in 子查询优化:尽量避免子查询,采用left join表连接

(2)模式匹配like '%xxx%': 在MYSQL中,like 'xxx%’ 可以用到索引,而like '%xxx%'则不行;利用覆盖索引来进行优化

(3)limit分页优化

(4)count(*)统计数据如何加快速度:利用辅助索引count(辅助索引)快于count(*);

(5)SQL语句中有or条件,则会用不到索引;将其改为union all结果集合并

(6)不必要的排序;

(7)不必要的嵌套select查询

(8)不必要的表自身连接、

(9)用where子句代替having子句

6.3 合理使用索引:索引有一定开销,例如写入和更新或删除操作时都需要更新索引。此外,只有当某列被用于where子句时,才能享受到索引性能提升的好处

(1)单列索引和联合索引的对比:联合索引遵循最左侧原则

(2)字段使用函数,将不能用到索引

(3)致命的无引号导致全表扫描,无法用到索引:

(4)当取出的数据量超过表中数据的20%时,优化器就不会使用索引,而是全表扫描

(5)考虑不为某些列建立索引:

(6)group by、order by优化

(7)MYSQL5.6 InnoDB引擎支持全文索引

(8)MYSQL5.6支持explain update/select

(9)MySQL5.6优化了index merge合并索引,即可以实现一条SQL可以使用两个索引了

7. my.cnf配置文件调优

7.1 per_thread_buffers优化:为每个连接到MySQL的用户进程分配内存

(1)read_buffer_size: 用于表的顺序扫描,表示每个线程分配的缓冲区大小。

(2)read_rnd_buffer_size: 用于表的随机读取,表示每个线程分配的缓冲区大小

(3)sort_buffer_size: 在表进行order by 和group by 排序操作时,由于排序的字段没有索引,会出现Using filesort,为了提高性能,可用此参数增加每个线程分配的缓冲区大小。

(4)thread_stack: 表示每个线程的堆栈大小

(5)join_buffer_size:

(6)max_connections: 该参数用来设置最大连接数,默认100。一般设置为512到1000即可。

7.2 global_buffers优化:用于在内存中缓存从数据文件中检索出来的数据块,可以大大提高查询和更新数据的性能。

(1)innodb_buffer_pool_size: 核心参数,默认为128MB

(2)innodb_additional_mem_pool_size:用来存储数据字典信息和其他内部数据结构,表越多,需要分配的内存越多,一版设置为16MB

(3)innodb_log_buffer_size: 事务日志所使用的缓冲区。

7.3 Query Cache在不同环境下的使用: 其功能是缓存select语句和结果集。查询缓存绝不会返回过期数据,当数据被修改后,在查询缓存中的任何相关词条都会被清除。

如果环境中写操作很多,不适合打开query_cache_type,如果读操作频繁而写操作很少,则打开query_cache_type=1。