mysql优化大全,如何让你的sql执行的更高效

mysql优化切入点:

  • 事前:

设计数据库时:数据库表、字段的设计(垂直分表),存储引擎 。

横向扩展:MySQL集群、负载均衡、读写分离,分库分表 。

  • 事中:

SQL语句的优化,利用好MySQL自身提供的功能,如索引等 。

  • 事后:

mysql 中的慢查询Explian查看执行计划,做分析,做优化。

数据库设计:

字段类型的选择,设计规范,范式,常见设计案例

一.表级设计规范:

1.数据库和表的字符集统一使用UTF8

2.字段命名要见名知一,所有表和字段都需要添加注释

3.单表字段不宜过多,冷热数据分离

Mysql限制每个表最多存储4096列,并且每一行数据的大小不能超过65535字节 减少磁盘IO,保证热数据的内存缓存命中率(表越宽,把表装载进内存缓冲池时所占用的内存也就越大,也会消耗更多的IO) 更有效的利用缓存,避免读入无用的冷数据 经常一起使用的列放到一个表中(避免更多的关联操作)

4.单表数据过多要考虑分表或者历史数据归档

单表数据量建议控制在500万以内,过大会造成修改表结构,备份,恢复都会有很大的问题
可以用历史数据归档(应用于日志数据),分库分表(应用于业务数据)等手段来控制数据量大小

二.字段级设计规范:

1.优先选择符合存储需要的最小的数据类型

  • 将字符串转换成数字类型存储,如: 将IP地址转换成整形数据

  • 对于非负型的数据(如自增ID、整型IP)来说,要优先使用无符号整型来存储

    • 无符号相对于有符号可以多出一倍的存储空间

      SIGNED INT -2147483648~2147483647
      UNSIGNED INT 0~4294967295

    • VARCHAR(N)中的N代表的是字符数,而不是字节数使用UTF8存储255个汉字 Varchar(255)=765个字节过大的长度会消耗更多的内存

2.尽可能使用 not null

非null字段的处理要比null字段的处理高效些!且不需要判断是否为null。

null在MySQL中,不好处理,存储需要额外空间,运算也需要特殊的运算符。如select null = null和select null <> null(<>为不等号)有着同样的结果,只能通过is null和is not null来判断字段是否为null。

如何存储?MySQL中每条记录都需要额外的存储空间,表示每个字段是否为null。因此通常使用特殊的数据进行占位,比如int not null default 0、string not null default ‘ ’。

3.避免使用ENUM类型

修改ENUM值需要使用ALTER语句
ENUM类型的ORDER BY操作效率低,需要额外操作
禁止使用数值作为ENUM的枚举值

4.使用TIMESTAMP(4个字节)或DATETIME类型(8个字节)存储时间

TIMESTAMP 存储的时间范围 : 1970-01-01 00:00:01 ~ 2038-01-19-03:14:07
TIMESTAMP 占用4字节和INT相同,但比INT可读性高
超出TIMESTAMP取值范围的使用DATETIME类型存储

经常会有人用字符串存储日期型的数据(不正确的做法)
缺点1:无法用日期函数进行计算和比较
缺点2:用字符串存储日期要占用更多的空间

5.同财务相关的金额类数据必须使用decimal类型

  • 非精准浮点:float,double
  • 精准浮点:decimal

Decimal类型为精准浮点数,在计算时不会丢失精度
占用空间由定义的宽度决定,每4个字节可以存储9位数字,并且小数点要占用一个字节
可用于存储比bigint更大的整型数据

三.索引的设计规范

1.限制每张表上的索引数量,建议单张表索引不超过5个

2.禁止给表中的每一列都建立单独的索引

3.每个Innodb表必须有个主键

4.常见索引列建议

  • 出现在SELECT、UPDATE、DELETE语句的WHERE从句中的列

  • 包含在ORDER BY、GROUP BY、DISTINCT中的字段,并不要将符合1和2中的字段的列都建立一个索引, 通常将1、2中的字段建立联合索引效果更好

  • 多表join…on…的关联列

5.如何选择索引列的顺序

建立索引的目的是:希望通过索引进行数据查找,减少随机IO,增加查询性能 ,索引能过滤出越少的数据,则从磁盘中读入的数据也就越少

  1. 区分度最高的放在联合索引的最左侧(区分度=列中不同值的数量/列的总行数)
  2. 尽量把字段长度小的列放在联合索引的最左侧(因为字段长度越小,一页能存储的数据量越大,IO性能也就越好)
  3. 使用最频繁的列放到联合索引的左侧(这样可以比较少的建立一些索引)

6.避免建立冗余索引和重复索引

建立冗余索引和重复索引会增加了查询优化器生成执行计划的时间。

重复索引示例:primary key(id)、index(id)、unique index(id) 冗 余索引示例:index(a,b,c)、index(a,b)、index(a)

7.对于频繁的查询优先考虑使用覆盖索引

覆盖索引:就是包含了所有查询字段(where,select,ordery by,group by包含的字段)的索引

覆盖索引的好处:

  1. 避免Innodb表进行索引的二次查询

Innodb是以聚集索引的顺序来存储的,对于Innodb来说,二级索引在叶子节点中所保存的是行的主键信息,
如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据
而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询 ,减少了IO操作,提升了查询效率

  1. 可以把随机IO变成顺序IO加快查询效率

由于覆盖索引是按键值的顺序存储的,对于IO密集型的范围查找来说,对比随机从磁盘读取每一行的数据IO要少的多,
因此利用覆盖索引在访问时也可以把磁盘的随机读取的IO转变成索引查找的顺序IO

SQL语句的优化:

1.避免数据类型隐式转换

所有存储相同数据的列名和列类型必须一致(一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低)

//todo 待续

猜你喜欢

转载自blog.csdn.net/weixin_43828467/article/details/115370895