.数据库优化的思路

1.SQL语句优化

1)应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
2)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3)很多时候用 exists 代替 in 是一个好的选择
4)用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤

2.索引优化

索引优化策略

  • 最左前缀匹配原则,上面讲到了
  • 主键外检一定要建索引
  • 对 where,on,group by,order by 中出现的列使用索引
  • 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0
  • 对较小的数据列使用索引,这样会使索引文件更小,同时内存中也可以装载更多的索引键
  • 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);
  • 为较长的字符串使用前缀索引
  • 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可
  • 不要过多创建索引, 权衡索引个数与DML之间关系,DML也就是插入、删除数据操作。这里需要权衡一个问题,建立索引的目的是为了提高查询效率的,但建立的索引过多,会影响插入、删除数据的速度,因为我们修改的表数据,索引也需要进行调整重建
  • 对于like查询,”%”不要放在前面。 
    SELECT * FROMhoudunwangWHEREunameLIKE'后盾%' -- 走索引 
    SELECT * FROMhoudunwangWHEREunameLIKE "%后盾%" -- 不走索引
  • 查询where条件数据类型不匹配也无法使用索引 
    字符串与数字比较不使用索引; 

3.数据库结构优化

1)范式优化: 比如消除冗余(节省空间。。) 2)反范式优化:比如适当加冗余等(减少join) 3)拆分表: 分区将数据在物理上分隔开,不同分区的数据可以制定保存在处于不同磁盘上的数据文件里。这样,当对这个表进行查询时,只需要在表分区中进行扫描,而不必进行全表扫描,明显缩短了查询时间,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个精心设置的分区可以将数据传输对磁盘I/O竞争均匀地分散开。对数据量大的时时表可采取此方法。可按月自动建表分区。
4)拆分其实又分垂直拆分和水平拆分: 案例: 简单购物系统暂设涉及如下表: 1.产品表(数据量10w,稳定) 2.订单表(数据量200w,且有增长趋势) 3.用户表 (数据量100w,且有增长趋势) 以mysql为例讲述下水平拆分和垂直拆分,mysql能容忍的数量级在百万静态数据可以到千万 垂直拆分:解决问题:表与表之间的io竞争 不解决问题:单表中数据量增长出现的压力 方案: 把产品表和用户表放到一个server上 订单表单独放到一个server上 水平拆分: 解决问题:单表中数据量增长出现的压力 不解决问题:表与表之间的io争夺
方案: 用户表通过性别拆分为男用户表和女用户表 订单表通过已完成和完成中拆分为已完成订单和未完成订单 产品表 未完成订单放一个server上 已完成订单表盒男用户表放一个server上 女用户表放一个server上(女的爱购物 哈哈)

数据库的分表分库

4.服务器硬件优化

这个么多花钱咯!

mysql的查询效率提升通常可以通过几个方面来回答:

数据库设计:

  建立索引:

    1.避免全表扫描,在设计where,order by的列上建立索引;

    2.索引对null值是不生效的,如果查询语句用到了null,则查询引擎会放弃使用索引,比如 select a from table where c is null; 所以建立索引字段的默认值最好不要为null;

    3.并不是所有索引都有效,sql会根据表中的数据进行查询优化的,当数据有大量重复时,查询可能不会去使用索引,比如sex一列中有男女,条数比例差不多,这样即使建了索引也没太大用处;

    4.索引不是越多越好,索引可以提高select的效率,但是对于insert或者update有可能会重建索引,所以需要视情况考虑。考虑一些索引是否有必要,一般一张表不建议超过6个,使用 show index in tablename查看。

    5.尽可能避免更新索引列,表变更会导致索引重新调整,耗费资源

  字段类型:

    1.尽量使用数字类型字段,若一个字段只包含数字类型不要设计为字符串类型,这会降低查询和连接的性能,且增加存储开销。这是因为引擎在处理查询和连接的时候会逐个比较字符串中的每个字符,而数字类型的只需要比较一次就可以了;

    2.尽可能的使用varchar/nvarchar代替char/nchar,因为变长存储空间小,可以节省空间;其实对于查询来说,在一个相对较小的字段内搜索效率肯定要高些;

  临时表:

    1.减少频繁的临时表创建和删除;

    2.如果使用到临时表,最后在存储过程中需要显示删除。避免系统表较长时间的锁定。

    3.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table

 

查询语句:

 避免全表扫描:

   1.尽量避免在where语句中使用!= 或<>,否则引擎将放弃索引而使用全表扫描;

   2.尽量避免在where语句中使用or条件,比如select a from table where b>10 or b<10;这样引擎也会使用全表扫描,可以使用union all来合并两个查询,如select a from table where b>10 union all select a from table where b>10;

   3.in或者not in 也要尽量避免,会导致全表扫描。如果是连续的数字,使用between代替;

   4.like语句得慎用,如果是全模糊匹配比如 like '%aaa%'这种是会全表扫描的,而使用like 'aaa%'这样还是使用到索引;

   5.尽量避免在where子句中使用表达式,否则引擎也会进行全表扫描,比如select a from table where b*2>10;

   6.尽量避免在where子句中使用函数,否则引擎也会进行全表扫描,比如select a from table where substring(c,0,10) like 'aaa%';

 其他避免:

   1.不要使用select * from ..,用具体字段代替*,不要返回一些不用的字段;

   2.避免使用游标;

   3.避免向客户端返回大量数据,可能考虑分页查询;

   4.避免大事务操作,提供并发;

   5.使用exist 代替in

代码方面:

  java方面:

    1.尽可能的少new对象;

    2.使用jdbc操作;

    3.合理利用内存,有的数据使用缓存;

    4.数据边读取边处理,不要一次性读到内存再处理;

    5.大量数据的操作和少量数据的操作要分开,这里涉及框架的选择;

    6.复杂sql使用执行计划查看,再具体优化;

10-06 15:14