MySQL使用规范手册,程序员必知必会( 三 )


3、尽量避免使用外键约束
不建议使用外键约束(foreign key) , 但一定要在表与表之间的关联键上建立索引;
外键虽然可以保证数据的参照完整性 , 但外键也会影响父表和子表的写操作从而降低性能 , 还会使得表更耦合 , 建议在业务端实现 。
五、MySQL数据库SQL开发规范
1、建议使用预编译语句进行数据库操作
预编译语句可以重复使用 , 相同的SQL语句可以一次解析 , 多次使用 , 减少SQL编译所需要的时间 , 提高处理效率;此外 , 还可以有效解决动态SQL带来的SQL注入问题 。
2、避免数据类型的隐式转换
隐式转换如:SELECT 1 + "1";数值型 + 字符型 的隐式转换有可能会导致索引失效 , 以及一些意想不到的结果等 。
3、充分利用表中存在的索引
1)避免使用双%号的查询条件
如 WHERE first_name like '%James%' , 若无前置% , 只有后置% , 则执行SQL语句时会用到列上的索引 , 双%号则不会使用列上的索引 。
2)一条SQL语句只能使用复合索引中的一列进行范围查询
例如有weight、age、sex三列的联合索引 , 在查询条件中有weight列的范围查询 , 则在age和sex列上的索引将不会被使用;因此 , 在定义联合索引时 , 若某列需要用到范围查询 , 则将该列放到联合索引的右侧 。
3)使用not exists 代替not in
因为not in 在SQL语句中执行时会导致索引失效 。
4、杜绝使用SELECT *  , 必须使用SELECT <字段列表> 查询
因为使用SELECT * 查询会消耗更多的CPU、IO和网络宽带资源 , 并且查询时无法使用覆盖索引 。
5、禁止使用不含字段列表的INSERT 语句
如:INSERT into table_name values ('1','2','3'); 改为带字段列表的INSERT 语句:INSERT into table_name('c1','c2','c3') values ('1','2','3');
6、避免使用子查询 , 可以把子查询优化为join 关联操作
但是 , 通常子查询在in 子句中 , 且子查询中为简单SQL(即不包含union、group by、order by、limit从句)时 , 才可以把子查询转化为join关联查询进行优化;
子查询性能差的原因:

  • 子查询的结果集无法使用索引 , 通常子查询的结果集会被存储到临时表中 , 不论是内存临时表还是磁盘临时表都不会存在索引 , 所以查询性能会受到一定的影响;
  • 由于子查询会产生大量的临时表也没有索引 , 所以会消耗过多的CPU和IO资源 , 产生大量的慢查询 。
7、避免使用JOIN 关联太多表
1)在Mysql中 , 对于同一个SQL关联(join)多个表 , 每个join 就会多分配一个关联缓存 , 如果在一个SQL中关联的表越多 , 所占用的内存也就越大;
2)如果程序中大量的使用了多表关联的操作 , 同时join_buffer_size(MySQL允许关联缓存的个数)设置的也不合理的情况下 , 就容易造成服务器内存溢出的情况 , 就会影响服务器数据库性能的稳定性;
3)此外 , 对于关联操作来说 , 会产生临时表影响查询效率 , 而Mysql最多允许关联61个表 , 建议不超过5个;
8、对同一列对象进行or 判断时 , 使用in 替代or
in 的值只要涉及不超过500个 , 则in 操作可以更有效的利用索引 , or 大多数情况下很少能利用到索引 。
9、禁止使用order by rand() 进行随机排序
10、禁止在WHERE 从句中对列进行函数转换和计算
因为在WHERE 从句中对列进行函数转换或计算时会导致索引无法使用 。
No推荐:
where date(end_time)='20190101'
推荐:
where end_time >= '20190101' and end_time < '20190102'
11、在明显不会有重复值时使用UNION ALL 而不是UNION
1)UNION 会把两个结果集的所有数据放到临时表中后再进行去重操作;
2)UNION ALL 不会再对结果集进行去重操作;
12、把复杂、较长的SQL 拆分为为多个小SQL 执行
1)大SQL在逻辑上比较复杂 , 是需要占用大量CPU 进行计算一条SQL语句;
2)在MySQL中 , 一条SQL 语句只能使用一个CPU 进行计算;
3)SQL拆分后可以通过并行执行来提高处理效率 。


推荐阅读