主要从如下几个方面考虑 MySQL 的性能优化:数据库系统级数据库设计级SQL 级应用程序级

 

  • 数据库系统级

1)适当增大 MySQL 允许的最大连接数 max_connections,防止并发数过多无法支撑。-- 一般来说 500 到 800 左右是一个比较合适的参考值。

2)需要排序且无法对 SQL 优化的情况下,可以适当增大内存 buffer 的大小:max_length_for_sort_data。

 

  • 数据库设计级

非索引层面:

1)选择简单的数据类型,能使用 int 型的就不要用字符型。--存储空间小 + 处理速度更快

2)考虑增加冗余字段。

3)记录行数太多,水平切分;列数太多,垂直切分。

4)字段尽量不要为 null,避免后续查询时使用 is null,导致不走索引。

索引层面:

1)按照语句解析的过程创建索引,比如 from .. on .. join .. where a=.. and b= .. group by .. having... select distinct c order by .. limit ...,创建的索引:(a, b, c)。

2)varchar 类型尽量根据区分度建立索引。区分度计算:

count(distinct left(列名, 索引长度)) / count(*)

--  节约索引空间 + 加快索引查找效率

 

  • SQL 级

单表:

1)查询条件,字符型和数值型写清楚,避免隐式转换导致不走索引。

2)不使用 select *,而是指明要查询的字段。-- 避免解析开销 + 不必要的网络传输开销

3)  不使用 is null,<>,!=,避免不走索引。-- 复合索引将导致自身以及右侧所有索引全部失效。

4)尽量不使用 or。

5)查询字段上不要做运算。

6)不要用 '%xx%' 进行模糊匹配,尽量以常量开头 'xx%';如果用了  '%xx%' 的话,尽量让其走覆盖索引,比如 select a where a like '%xx%'。

7)in 语句可能会造成不走索引,尽量将该条件写在多个查询条件的后面。-- 据说 in 查询出的结果集大于总数据量的 50% 会导致全表扫描,总之可能导致索引失效

8)根据索引列的最左匹配原则,保持 where 后使用的顺序和索引的定义一致,不要跨列使用索引。--乱序使用,会导致部分索引失效;跨列使用,在 order by 中可能会导致 using filesort,影响性能。

9)批量 insert 时,采用 「insert ..values(1),(2),(3)」,而不是「insert values (1); insert values (2); insert values (3)」。

多表:

1)关联字段必须有索引。

2)原则:小表驱动大表,典型案例就是 in 和 exists:

select .. from A where A.id in (select B.id from B),in 后面接的 B 是驱动表;

select .. from A where exists .. B.id = A.id,exists 前面的 A 就是驱动表,所以尽量用小表去驱动大表。

 

  • 应用程序级

1)语句尽量使用预编译。

2)批量插入可以使用多线程。

3)在允许的情况下,分批次提交事务,而不是一次提交一个大的事务。