mysql开发优化点

一、字段
1,尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNED;
2,VARCHAR的长度只分配真正需要的空间;
3,使用枚举或整数代替字符串类型;
4,尽量使用TIMESTAMP而非DATETIME;
5,单表不要有太多字段,建议在 20 以内;
6,避免使用 NULL 字段,很难查询优化且占用额外索引空间;
7,用整型来存 IP。
8,如果其他数据需要经常需要查询,而 blob/text 不需要,则将 blob/text 数据域其他数据分离。
9,压缩 text 和 blob 数据类型 — 为了节省空间,减少从磁盘读数据。




二、索引


1,索引并不是越多越好,要根据查询有针对性的创建,考虑在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描;
2,应尽量避免在WHERE子句中对字段进行NULL值判断,否则将导致引擎放弃使用索引而进行全表扫描;
3,值分布很稀少数据重复即区分度很低的字段不适合建索引,例如 "性别",真假值 这种只有两三个值的字段;
4,字符字段只建前缀索引;
5,字符字段最好不要做主键;
6,不用外键,由程序保证约束;
7,尽量不用UNIQUE,由程序保证约束;
8,使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引。
9,频繁更新的字段不适合建立索引
10,where条件中用不到的字段不适合建立索引,都用不到建立索引没有意义还浪费空间
11,表数据可以确定比较少的不需要建索引
12,参与列计算的列不适合建索引
13,大字段(blob)不要建立索引,查询也不会走索引。
14,当时间存储为时间戳保存的可以建立前缀索引。
15,当一个表中有100万数据,而经常用到的数据只有40万或40万以下,是不用考虑建立索引的,没什么性能提升。
16,在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
17,负向条件查询不能使用索引,可以优化为 in 查询。负向条件有:!=、<>、not in、not exists、not like 等。
18,联合索引最左前缀原则(又叫最左侧查询),如果在(a,b,c)三个字段上建立联合索引,那么它能够加快 a | (a,b) | (a,b,c) 三组查询速度。
如果建立了(a,b)联合索引,就不必再单独建立 a 索引。同理,如果建立了(a,b,c)联合索引,就不必再单独建立 a、(a,b) 索引。
19,范围列可以用到索引(联合索引必须是最左前缀)。范围条件有:<、<=、>、>=、between等。范围列可以用到索引(联合索引必须是最左前缀),但是范围列后面的列无法用到索引,索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。
假如有联合索引 (empno、title、fromdate),那么下面的 SQL 中 emp_no 可以用到索引,而 title 和 from_date 则使用不到索引。
select * fromemployees.titles where emp_no < 10010' and title='Senior Engineer'and from_date between '1986-01-01' and '1986-12-31'
20,如果有 order by、group by 的场景,请注意利用索引的有序性。
order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。
例如对于语句 where a=? and b=? order by c,可以建立联合索引(a,b,c)。
如果索引中有范围查找,那么索引有序性无法利用,如 WHERE a>10 ORDER BY b;,索引(a,b)无法排序。
21,单表索引建议控制在5个以内,单索引字段数不允许超过5个。字段超过5个时,实际已经起不到有效过滤数据的作用了。
22,SQL 性能优化 explain 中的 type:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。
consts:单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
ref:使用普通的索引(Normal Index)。
range:对索引进行范围检索。
当 type=index 时,索引物理文件全扫,速度非常慢。
23,业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的。
另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
24,建立索引的列,不允许为 null。单列索引不存 null 值,复合索引不存全为 null 的值,如果列允许为 null,可能会得到“不符合预期”的结果集,所以,请使用 not null 约束以及默认值。
25,超过三个表最好不要 join。需要 join 的字段,数据类型必须一致,多表关联查询时,保证被关联的字段需要有索引。
26,保证索引简单,不要在同一列上加多个索引。
27,有时,增加列时,先删除索引,之后在加上索引会更快。
28,不得使用外键与级联,一切外键概念必须在应用层解决
29,总结一条:
选择唯一性索引;
为经常需要排序、分组和联合操作的字段建立索引;
为常作为查询条件的字段建立索引;
限制索引的数目;
尽量使用值小的索引;
尽量使用前缀来索引,如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。
删除不再使用或者很少使用的索引;
最左前缀匹配原则,非常重要的原则;
索引列不能参与计算,保持列“干净”。
尽量的扩展索引,不要新建索引。 比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可






三、查询
1,可通过开启慢查询日志来找出较慢的 SQL;
2,不做列运算:SELECT id WHERE age + 1 = 10,任何对列的操作都将导致表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边;
3,SQL 语句尽可能简单:一条 SQL 只能在一个 CPU 运算;大语句拆小语句,减少锁时间;一条大 SQL 可以堵死整个库;
4,不用SELECT *;
5,OR改写成IN:OR的效率是 n 级别,IN的效率是 log(n) 级别,in 的个数建议控制在 200 以内;
6,不用函数和触发器,在应用程序实现;
7,避免%xxx式查询;
8,少用JOIN;
9,使用同类型进行比较,比如用'123'和'123'比,123和123比;
10,尽量避免在WHERE子句中使用!= 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描;
11,对于连续数值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5;
12,列表数据不要拿全表,要使用LIMIT来分页,每页数量也不要太大。
13,使用count统计数据量的时候建议使用count(*)而不是count(列),因为count(*)MySQL是做了优化的。
14,什么时候开MySQL的查询缓存? 交易系统(写多、读少)和SQL优化测试,建议关闭查询缓存;论坛文章类系统(写少、读多),建议开启查询缓存。
15,复杂SQL语句优化的思路:首先考虑在一个表中能不能取到有关的信息,尽量少关联表,关联条件争取都走主键或外键查询条件,能走到对应的索引,https://gw.alicdn.com/tps/TB10M0wLpXXXXaaaXXXXXXXXXXX-109-109.png
争取在满足业务上走小集合数据查找,INNER JOIN 和子查询哪个更快,场景不一致速度也不同
16,where条件多条件一定要按照小结果集排大结果集前面
17,尽量避免大事务操作,提高系统并发能力,有时无法避免,改用定时器延迟处理。
18,使用UNION ALL 替换OR多条件查询并集,尽量用 union all 代替 union。
19,在大数据表删除也是一个问题,避免删除过程数据库奔溃,可以考虑分配删除,一次删1000条,删完后等一会继续删除
20,如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
21,尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
22,尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
23,很多时候用 exists 代替 in 是一个好的选择:select num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num)
24, 二次SQL查询区别不大的时候,不能按照二次执行的时间来判断优化结果,没准第一次查询后又保存缓存数据,导致第二次查询速度比第二次快,很多时候我们看到的都是假象。
25,在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送DONE_IN_PROC 消息。
26,页面搜索严禁左模糊或者全模糊,如果需要可以用搜索引擎来解决。
27,如果明确知道只有一条结果返回,limit 1 能够提高效率。
28,使用 INSERT ON DUPLICATE KEY 或 INSERT IGNORE 来代替 UPDATE,避免 UPDATE 前需要先 SELECT。
29,如果合适,用 GROUP BY 代替 DISTINCT。
30,利用延迟关联或者子查询优化超多分页场景。
MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。
31,使用 ISNULL()来判断是否为 NULL 值,注意,NULL与任何值的直接比较都为 NULL
32,禁止单条SQL语句同时更新多个表。
33,减少与数据库交互次数,尽量采用批量SQL语句。

猜你喜欢

转载自blog.csdn.net/zhanjianshinian/article/details/80690849