MySQL数据库优化

1. 添加索引

MySQL数据库的四类索引: 

  index  ----  普通索引,数据可以重复,没有任何限制。
  unique   ---- 唯一索引,要求索引列的值必须唯一,但允许有空值;如果是组合索引,那么列值的组合必须唯一。

  primary key ---- 主键索引,是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值,一般是在创建表的同时创建主键索引。

  组合索引 ----  在多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。

  fulltext ---- 全文索引,是对于大表的文本域:char,varchar,text列才能创建全文索引,主要用于查找文本中的关键字,并不是直接与索引中的值进行比较。fulltext更像是一个搜索引擎,配合match against操作使用,而不是一般的where语句加like。

  注:全文索引目前只有MyISAM存储引擎支持全文索引,InnoDB引擎5.6以下版本还不支持全文索引

  所有存储引擎对每个表至少支持16个索引,总索引长度至少为256字节,索引有两种存储类型,包括B型树索引和哈希索引。

  索引可以提高查询的速度,但是创建和维护索引需要耗费时间,同时也会影响插入的速度,如果需要插入大量的数据时,最好是先删除索引,插入数据后再建立索引。

 
索引的创建原则: 
  1. 选择唯一性索引。
  2. 为经常需要排序(ORDER BY),分组(GROUP BY)和联合操作(JOIN)的字段建立索引。
  3. 为经常被作为where子句查询条件的字段建立索引。
  4. 限制索引的数目。
  5. 尽量使用数据量少的索引。
  6. 尽量使用前缀来创建索引。如果字段的值很长,最好使用值的前缀来索引,这样可以大大节约索引空间,从而提高索引效率。其缺点是不能用于ORDER BYGROUP BY操作,也不能用于覆盖索引 Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)。
  7. 删除不再使用或者很少使用的索引。
  8. 在不同值较少的字段上不必要建立索引,如性别字段;
  9. 尽量不要对数据库中某个含有大量重复的值的字段建立索引(ENUM类型的)
  10. 对于经常存取的列避免建立索引;
  11. 用于联接的列(主健/外健)上建立索引;

索引使用注意 :

(1). 对于like语句,以%或者‘_’开头的不会使用索引,以%结尾会使用索引。
(2). 表的主键、外键必须有索引。
(3). 不同值越多、同值最少的列建立索引,区分度的公式:count(distinct(字段))/count(*)
(4). 单表的数据太少,不适合建索引。
(5). where,order by ,group by 等过滤时,后面的字段最好加上索引。
(6). 尽量不要使用 not in和 <> 操作。
(7). 尽量不要在列上进行运算(函数操作和表达式操作)。
(10). 列中包含NULL值,会导致无法使用到索引。

 

2. 尽量把字段设置为NOT NULL

NOT IN != 等负向条件查询,如果在有NULL值的情况下返回永远为空结果,查询容易出错

将来数据库执行查询操作的时候,数据库不用去额外比较NULL值。

NULL列需要一个额外字节作为判断是否为NULL的标志位,使用NULL时和该列其他的值可能不是同种类型,导致问题。

避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

3. 选取最适用的字段属性

对于那些可能值很有限的列,使用tinyint代替VARCHAR

  比如记录移动设备平台,只有两个值:android,ios,那么就可以使用0表示android,1表示ios,这种列一定要写好注释

  为什么不用ENUM呢?ENUM扩展困难,比如后来移动平台又增加了一个ipad,那岂不是懵逼了,而tinyint加个2就行,而且ENUM在代码里面处理起来特别奇怪,是当成整形呢还是字符串,一定要在数据库注释或者代码里面写明各个值的含义

对于那些定长字符串,可以使用char,比如邮编,总是5位

对于那些长度未知的字符串,使用varchar

不要滥用bigint,比如记录文章数目的表id字段,用int就行了

4. 不使用 NOT IN 和 <> 操作
NOT IN和<>操作都不会使用索引,将会进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3 则可使用 id>3 or id<3 来代替。

5. 使用连接(JOIN)来代替子查询(Sub-Queries)

因为使用连接查询时,MySQL不需要在内存中创建临时表来完成查询逻辑

6. 优化查询语句

尽量使用简单的查询,避免使用表链接

多条件查询时,请把简单查询条件或则索引列查询置于前面

尽量指定需要查询的列,不要偷懒使用select *

使用子查询会创建临时表,会比链接(JOIN)和联合(UNION)稍慢

在索引字段上查询尽量不要使用数据库函数,不便于缓存查询结果

当只要一行数据时,请使用LIMIT 1,如果数据过多,请适当设定LIMIT,分页查询.

千万不要 ORDER BY RAND(),性能极低

7. 添加缓存

对于一些经常访问到的数据而且不需要经常变化的数据放在缓存中,比如配置信息等,可以放在缓存能节约磁盘IO 

栗子: a. 可以在本地,缓存数据库的表结构

    b. 缓存的数据一定要注意及时更新,还有设置有效期

    c. 增加缓存务必会增加系统复杂性,一定要注意权衡

8. 将会导致全表搜索的操作

尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描

尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

尽量避免在 where 子句中使用 like模糊匹配 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描

in 和 not in 也要慎用,否则会导致全表扫描

对于连续的数值,能用 between 就不要用 in , 用 exists 代替 in

在 where 子句中使用参数,也会导致全表扫描,例如: select id from t where num = @num , 修改为: select id from t with(index(索引名)) where num = @num

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

尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描

不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引

9. 使用merge存储引擎实现分表

  a. 将大表拆分为多张小表

   b. 将耦合度过高的表进行分离

   c. 垂直分表:不经常读取的数据放入一张表中,提高磁盘读取效率。

10. 主从分离: 采用主从分离模式,将数据库的查询操作和写入操作分离

11. 进行架构级别的缓存,页面静态化和分布式存储

12. 速度优先级

CPU运行速度 > 内存访问速度 > 磁盘io访问速度 > 网络请求速度

原文地址:https://www.cnblogs.com/hsmwlyl/p/10576004.html