美文网首页
一、Mysql优化

一、Mysql优化

作者: 布衣码农 | 来源:发表于2019-06-08 16:02 被阅读0次

1. 表锁

表锁开销小,加锁快,不会出现死锁,并发度低
一般updatedelete操作会使用表级锁。全表扫描和 group by 也会使用表级锁

2.行锁

行锁开销大,加锁慢,会出现死锁(Innodb 对死锁有自动回滚机制),并发度高

锁阀值: 这个值表示一个锁超过60秒就会被释放,并报错
可以查看变量innodb_lock_wait_timeout

show variables like 'innodb_lock_wait_timeout';

结果显示


image.png
// 查看全局锁阀值
show global variables like 'innodb_lock_wait_timeout'
// 设置全局锁阀值
set global variables innodb_lock_wait_timeout=100

3.锁在Myisam、Innodb引擎上的表现

Myisam是表级锁。
加读锁不会阻塞读,但会阻塞写。加写锁会阻塞所有。

Innodb是行级锁,是存储引擎通过索引加锁实现的。只有通过索引检索出来的数据,InnoDB才会使用行级锁,否则InnoDB还是回使用表级锁。

缓存优化

1.mysql缓存查询状态

show variables like '%query_cache%'

2.缓存失效场景

a)大小写不同的 sql语句
关键字大小写,保留关键字 "``",where统一条件使用单引号或者双引号
因为query cache在内存中是以hash结构来映射的,所以 sql语句的规范尽量保持一致(很多框架目前都有 ORM ,尽量少的直接手写 sql)

b)事务隔离级别为 serializable 查询语句不缓存
c)mysql函数 now(),current_date()等
d)用户自定义函数
e)存储函数
f)临时表
g)局部变量
h)权限不足
i)子查询
j)预存储语句

如何优化查询缓存(提高查询缓存命中率)
1.通过分区表提高缓存命中率 。
2.尽量一次性写入
3.指定query_cache_type=2(demand),查询时自己定义 SQL_CACHE,SQL_NO_CACHE
4.基于数据库连接设置或者运行缓存
5.对于写操作非常频繁的的表,不要使用缓存,否则会造成缓存频繁修改,没有意义,使用query_cache_type=0设置

对于 innodb存储引擎有几个关键字段需要注意
1.innodb_buffer_pool:数据库索引、表数据缓存
2.innodb_buffer_pool_read_requests:读的次数
3.innodb_buffer_pool_reads:从磁盘读取的次数
4.innodb_buffer_pool_pages_data:有数据的缓存页数
5.innodb_buffer_pool_pages_total:缓存页数的总数量 16k * 65535 = 8M
6.innodb_buffer_pool_pages_free 没有使用缓存的页数,这个数字越大使用内存越小,这个数字越小需要调大内存在my.cnf中通过innodb_buffer_pool_size字段设置内存大小

命中率公式 : (innodb_buffer_pool_read_requests - innodb_buffer_pool_reads) / innodb_buffer_pool_read_requests

注意:
缓存并不是所有场景都能带来预期的性能改善
在大量写操作的场景时, cache机制可能会让性能下降。因为每次写操作会让系统去做 cache失效操作,这样会造成不小的开销。

另外 cache的访问是由一个全局锁来控制的,这样大量的查询会被阻塞,直到锁被释放。

很多时候我们会将热数据放入缓存数据库(memcached、 redis等)以减轻 数据库的压力

索引优化

1. 优化原则

通过 profile跟explain分析

  1. 如果语句执行时间超出容忍范围,优化表设计、索引、sql语句
  2. 如果语句等待时间过长,考虑调整服务器参数(缓冲区、线程数)必要时需要升级 内存、cpu

2.索引

关系型数据库存储是有序的,正常就是直接进行全表扫描,建立 btree或者 hash索引以后,通过索引来查询数据能够大大的提升查询效率,注意:一条数据查询只会用一个索引

3.索引类型

Btree:是Myisam、InnoDB 默认的索引,对于排好序的数据能够快速查找到结果
Hash:虽然 hash性能很高,但不能进行范围查询、排序等。使用过 memcache、redis之类的缓存数据库应该都能理解 通过 set的数据想用 get获取一个范围数据很难。

4.使用索引的场景

不以通配符%开头的like语句

// 假设此时field1为索引
SELECT field1,field2 FROM Table1 WHERE field1 LIKE'test%';

order bygroup by 使用索引

// 假设此时field1为索引
SELECT field1,field2 FROM Table1 ORDER BY field1
SELECT field1,field2 FROM Table1 GROUP BY field1

对于范围使用索引if null , between> , =,<

// 假设此时field1为索引
SELECT field1,field2 FROM Table1 WHERE field1 > 100

TODO 未完待续

相关文章

网友评论

      本文标题:一、Mysql优化

      本文链接:https://www.haomeiwen.com/subject/jejixctx.html