mysql系列—超详细调优策略

数据库调优

MySQL 调优分析 explain;show status 查看服务器状态信息

SQL 语句 的优化

分析:确认程序是否存在查询不需要的记录;mysql 是否在扫描额外记录

  1. 查询不需要的记录:使用 select 语句查询大量结果,然后再获取前 N 行(如新闻网站,取 100 条记录,只显示前面的 10 条),这时可以使用 limit(limit 1,10;从 1 开始 10 行)

  2. 总是使用 SELECT *,对 I/O、内存消耗较大,不必要时不要这样。

  3. 子查询的性能又比外连接性能慢,尽量用外连接来替换子查询。
    Select* from A where exists (select * from B where id>=3000 and A.uuid=B.uuid);

    一种简单的优化就是用 inner join 的方法来代替子查询,查询语句改为:
    Select* from A inner join B using(uuid) where b.uuid>=3000;

  4. 尽量少排序,排序操作会消耗较多的 CPU 资源(可以使用索引)

  5. 对于连续的数值,能用 between 就不要用 in 了:

    select id from t where num between 1 and 3
    
  6. 切分查询,将大查询切分成小查询,每个查询功能一样,只完成一小部分,如果用一个大的语句一次性完成的话,则可能需要一次锁住很多数据、耗尽系统资源、阻塞很多小的但重要的查询。

索引的优化

  1. 建立索引加快查询性能,优先在经常搜索的字段上建立索引(where);WHERE 子句的查询条件里使用了比较操作符 LIKE 前置通配符%(如:LIKE “%ABC”),因为‘%’代表任何字符,%xxx 不知道怎么去索引的,所以使用不了索引。只要列中包含有 NULL 值都将不会被包含在索引中(复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。)
  2. 应尽量避免在 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

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。请注意,UNION 内部的SELECT 语句必须拥有相同数量的列列也必须拥有相似的数据类型。不是同一个表也可以union,,条件是只要列数相同,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。UNION ALL 允许重复

  1. in 和 not in 也要慎用,否则会导致全表扫描,如:
    select id from t where num in(1,2,3)

  2. 索引列不能是表达式的一部分,也不能是函数的参数。下列索引列在表达式中因此使用全表扫描
    select * from user where age + 1 =20;

  3. 应尽量避免在 where 子句中使用 !=<> 操作符,否则将引擎放弃使用索引而进行全表扫描

  4. 在多个列上建立独立的单列索引大部分情况下不能提高查询性能,可以使用复合索引(多列索引),key(name,age,sex)

    多列索引有一个特点,即最左前缀(Leftmost Prefixing)(索引必须从最左边开始比对)。假如有一个多列索引为key(firstname,lastname ,age),当搜索条件是以下各种列的组合和顺序时,MySQL 将使用该多列索引:
    firstname,lastname,age
    firstname,lastname
    firstname
    lastname,firstname(应该也可以,有优化器的存在

    也就是说,相当于还建立了 key(firstname lastname)和 key(firstname)。但是只搜 lastname用不到索引

  5. 由于复合索引最左前缀匹配,将搜索次数多的列放到最前列(建立 B+树时从最左字段开始排序,第一个字段相同才排第二个字段,因为查找树需要一定的顺序)

  6. 尽量选择小而简单的数据类型做索引,减少磁盘空间

  7. 有时候需要索引很长的字符列,这会让索引变得大且慢。一个方式是使用哈希索引,另一个是使用前缀索引,即索引开始的部分字符串,这样可以节约索引空间,提高效率。但这样会降低索引的选择性(不重复的索引值/记录总数)。索引的选择性越高则查询效率越高,唯一索引的选择性是 1,性能是最好的。一般情况,某个前缀的选择性也是足够高的

数据库表结构的优化(第四章

  • 选择合适的数据类型
    数据类型越小越好:尽量使用可以正确存储数据的最小数据类型(tinyint,占用更少的磁盘、内存、cpu 缓存);tinyint 占 1 字节,int 占 4 字节
  • 简单就好:如整型比字符操作代价更低(用整型存储 ip 地址)
  • 避免 NULL:最好指定列为 NOT NULL,因为 NULL 更难优化,使用的索引更复杂
  • 不要设计太多列:减少不必要的列
  • 适度冗余,减少 join 关联查询
  • 适当拆分,水平拆分、垂直拆分
  • 选择合适的字符编码:如果我们可以确定不需要存放多种语言,就没必要非得使用 UTF8 或者其他 UNICODE 字符类型,这回造成大量的存储空间浪费

MySQL 配置文件 优化

​ mysql 的配置文件名为 my.cnf(window 为 my.ini),不同情况下配置文件参数设置也不相同,应该根据具体场景调优。

InnoDB 中最重要的选项是:

  • innodb_buffer_pool_size:缓存用户表(实际数据 row)及索引数据的最主要缓存空间,对 Innodb 整体性能影响也最大,默认为 8MB,建议设为内存的 70%~80%(MyISAM 只缓存索引)
  • innodb_log_file_size:日志文件大小,默认为 48MB,应该调大,至少有几百 MB

硬件的优化

CPU 的选择

最好的选择是核心数多并且主频高的。但是有时考虑成本问题,可以参考以下情况:

  • 如果不是密集型的查询,优先选频率高的,而不是数量多的
  • 如果是密集型的、高并发的查询,比如秒杀等活动,优先选更多的 cpu。因为一条 sql 语句只能在一个 cpu 上执行
内存的选择

​ 内存并不是容量越大,性能提升越明显。如果内存大小已经超过了总数据量的大小,那么即使再增加内存,系能提升也不会特别明显。

内存频率选择 cpu 支持的最高的频率,品牌、型号、规格等要一致。

磁盘配置和选择

各种磁盘性能比较:

PCIe > SSD > Raid10 > 磁盘 > 网络存储

各种磁盘的特点和应用:

  • 传统硬盘:需要考虑存储容量、传输速度、访问时间、主轴转速、物理尺寸等参数
  • raid 增加传统硬盘性能:主服务器建议用 raid10,从服务器可以 raid0(raid0:数据等量放置在 2 块磁盘中,raid1:让同一份数据完整保存在两块磁盘)
  • SSD 或者 PCIe 卡(FusionIO):缺点比传统硬盘更容易坏
    • SSD 应用场景:适用于存在大量随机 I/O 场景(SSD 随机 I/O 快)、适用于解决单线程负载的 I/O 瓶颈(用在从服务器上,适用于读的场景,频繁写会减少使用寿命)
  • 网络存储场景(NAS、SAN):数据库备份
操作系统

合理配置操作系统参数,选择合适的文件系统

加缓存 redis

先读写分离,再垂直拆分,再水平拆分

分库:根据业务逻辑垂直拆分

分表:

  • 纵向分表(常见为忙闲分表)
  • 横向切表
    • 等分切表,如哈希切表或其他基于对某数字取余的切表(USERID 奇数、偶数)。等分切表的优点是负 载很方便的分布到不同服务器;缺点是当容量继续增加时无法方便的扩容,需要重新进行数据的切分或转表。而且一些关键主键不易处理。
    • 递增切表,比如每 1kw 用户开一个新表,优点是可以适应数据的自增趋势; 缺点是往往新数据负载高,压力分配不平均。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值