美文网首页Java 核心技术MySQLJava Web知识
表设计、sql、应用层-简单实用的数据库优化建议

表设计、sql、应用层-简单实用的数据库优化建议

作者: 路过的猪 | 来源:发表于2018-03-01 18:12 被阅读21次

引言

本文主要通过数据库表设计、sql处理、应用层优化三个层面,来谈谈笔者在工作中的一些心得和建议。

合理设计数据库表

合理添加索引

(1)经常进行条件查询(where或join on)的字段考虑加上索引

(2)经常分组(GROUP BY)或排序(ORDER BY)的字段考虑加上索引(Btree)

(3)差异性大的字段才适合建立索引

差异性表示某行数据的字段在所有数据中是否足够独特,鹤立鸡群。就好像qq号,独一无二,全部数据中的qq号都不一样;相对而言,性别男或者女,都有近一半是相同的,这时候加上索引效果并不理想。

有一种情况,例如某个文章的状态status(0未审核,1审核通过待发布,2已发布,3审核不通过),我们应用层有个定时器(10秒一次)在扫数据库中 审核通过待发布的,然后进行发布,更新status为2。在实际数据中,尽管大部分数据都是已发布(差异性小),但审核通过待发布的数据是非常少的(差异性较大),这时候也可以考虑加上索引(用于where status=1的条件查询则非常有效)。

(4)当需要保证数据某个重要字段的唯一性时,考虑加上唯一索引(做数据库级别的限制往往能避免很多因为错误数据导致的问题)

注:索引并不是越多越好,因为增加索引后,新增(insert)或更新对应字段(update)时,索引会做对应的调整,效率会有一定影响,索引越多影响越大。

表字段个数不要太多

  • 简化业务逻辑开发
  • 当字段太多时,插入数据时,其中往往有许多用不上(默认值),会占用空间(null值也会占用空间)
  • 防止应用层直接select * 情况下取了多余的无用数据

我们公司是建议业务相关字段10个以内。

一般最初设计阶段,某个业务表有很多字段时,可以考虑拆分。一是按业务逻辑分、二是根据预估使用频率分。

避免使用触发器、函数、存储过程等

函数、触发器这些往往在应用层就能处理,而开发人员可以直接管理,并不需要和DBA打过多的交道,移植也方便。

另外数据库是拿来存数据的,除了增删改查,其他都不建议让数据库层面来干了。

注意 varchar 长度,取合理长度即可

varchar 超过255会多1个字节存储该字段值的长度;比如varchar(255)使用1个字节存储值长度,而varchar(256)则需要2个。

而定义的长度会影响对应的索引长度,比如 varchar(100) 和 varchar(20) 其对应建立的索引,前者要比后者的长度要大。

所以在满足业务场景的前提下,尽量取小的值即可。

小数(点)的设计,考虑使用decimal

在业务中往往包含一些小数的设计,例如价格(9.99元)、重量(51.3kg)等。

因为float和double这种浮点类型都存在精度问题,当需要较高精度时,可以使用decimal来取代;

另外一种达到要求精度的方案是降低字段表示的单位,从而消除小数,例如9.99元=999分,51.3kg=51300g,对应的字段使用整数表示即可。这种设计可能会增加应用层的复杂度(需要单位转换等),但如果经常进行排序的话,会有一定优势。

而在一些金融相关的行业,有时候往往不仅仅精确小数点后面两三位,而是4位、5位甚至更多位(例如0.9065元),这时候最好使用decimal。

注:decimal(10,4) 中,4表示小数位数,插入时超出则进行截取;10表示含小数在内的最多位数,这里整数则最多 (10-4) 位,超出时则报错。

sql篇

尽量避免联表查询

  • 联表查询时,数量尽量不要超过2个
  • 使用单表某些数据缓存(redis、memcached等)+ 应用层代码实现联表查询
  • 必要时,联表查询的条件列加上索引

大量数据时需要分页时 用索引字段条件查询 + limit N 替代直接 limit M,N

在大量数据时,mysql的limit M,N分页是存在比较严重的性能问题的,因为其会扫足前面M+N条数据,然后再取N条;当M非常大时,如2000万+时,效率就会非常慢了(10s+);

其中一个解决方法是:适当结合索引字段(如主键id)+ limit N 就能避免这个问题。

如 :select id, userName from t_user limit 20 000 000, 50;

假设第2000万条数据的id为 22 000 000;

改为:select id, userName from t_user where id >= 22 000 000 limit 50;

尽管在实际中客户端往往没有这样需求(页码太大),但当需要加载所有数据时则经常用到(如缓存预热)。

不要对条件查询的字段进行运算或函数操作

反例

(1) select id from t_user where age/2 > 10;

(2) select id from t_user where year(birthday) < 2000;

当age或birthday存在索引时,上面的语句并不会使用索引,而是直接进行全表扫描。

修改为

(1) select id from t_user where age > 20;

(2) select id from t_user where birthday < '2000-01-01';

上面的转换均可以在应用层的代码实现,尽量不要在数据库层面进行运算操作。

经典优化

  • name字段有索引,name like '%zhang%' 没有用上索引,而name like 'zhang%'则用上。
  • 联合索引(name, age) 最左匹配,where name='li' 或 where name='li' and age=18 用上该索引,而where age=18 则无法用到该索引。
  • 连接查询一般 优于 子查询
  • exist 优于 in
  • 范围查询 between and 优于 in
  • insert into t values(..),(..); 优于多条 insert into t (...);,因为前者索引只做了一次调整。

应用层优化

能在应用层处理的就不要在数据库处理

数据库连接数量时有限的,数据库处理的东西越少,压力越小,处理时间越短,连接放回连接池的速度就越快,整个应用的吞吐量也会随之增大。

所以一些条件运算、函数计算等都可以尽量在应用层面进行。

注:要综合考虑代价,不要什么都不管就往应用层里面怼。当运用到索引的分组、排序往往在数据库中处理效率更高。

合理利用缓存

一些热点数据可以进行缓存,这时候大流量下,可以大大减少DB的压力。

注:要注意缓存的管理,尽量保证数据一致性,在分布式环境下,应用本地缓存往往是不适用的(可以考虑redis等对缓存进行集中管理)。

利用消息机制进行异步DB操作

高并发下,DB往往扛不住,要么直接被压垮,要么连接数远远不够用。

目前来说,利用消息机制进行异步处理(相关DB操作)是一个不错的选择,因为消费的线程数量是有限的(DB可以承受的范围),这时候DB不会有那么大的压力,可以保证整个应用和DB都正常运行。

当结合缓存时,就能保证异步处理期间,仍认为数据已经被正常处理的了,因为取数据时,优先取缓存中的而不是DB。

选择适合的框架

为了简化开发往往会选择对DB操作的框架,而这个的选择在数流量/数据量小时往往没有什么区别。但是一旦到哪里都在抠性能时,这里的优化往往是非常重要的。

一个是考虑公司情况(对哪种框架处理更有经验),另外一个是考虑业务场景,不同的框架往往有其擅长的地方。

如果选择不合适(可能框架本身原因,肯能是因为对框架缺乏了解),想要优化时,往往显得捉襟见肘,难以应对。

总结

  1. 数据库是拿来存东西的,擅长的是增删改查,而不是各种逻辑处理和计算
  2. 结合实际业务场景,才能设计出最合理的字段,不长不短,不多不少
  3. sql优化归根结底都是怎样把索引给用上,把索引的作用最大化
  4. 善用缓存

相关文章

  • 表设计、sql、应用层-简单实用的数据库优化建议

    引言 本文主要通过数据库表设计、sql处理、应用层优化三个层面,来谈谈笔者在工作中的一些心得和建议。 合理设计数据...

  • 数据库的优化方案及如何提高查询效率

    数据库优化方案 优化索引,sql语句,分析慢查询 设计表的时候严格按照数据库设计规范来设计数据库 使用缓存,把京城...

  • MySQL 优化

    工作时SQL优化步骤 开启慢查询日志explain分析show profileSQL数据库服务器的调优 设计表优化...

  • MySQL优化框架

    1,SQL语句优化 2,索引优化 3,数据库结构优化 4,InnoDB表优化 5,MyISAM表优化 6,Memo...

  • 数据库的优化

    1.优化索引、SQL 语句、分析慢查询;2.设计表的时候严格根据数据库的设计范式来设计数据库;3.使用缓存,把经常...

  • 高并发 负载均衡 高可用

    高并发解决方案: 1)数据层 数据库集群和库表散列 分表分库 开启索引 开启缓存 表设计优化 Sql语...

  • Mysql数据库优化

    数据库优化顺序:Sql及索引->数据库表结构->系统配置->硬件 第一章:Sql语句优化 如何判断有问题Sql? ...

  • MySQL优化笔记(四)--表的设计与优化(单表、多表)

    前面讲了SQL优化以及索引的使用、设计优化了,那么接下来就到表的设计与优化啦!!!真实地去设计优化单表结构以及讲述...

  • MySQL高级使用和特性

    问题: 索引 如何分区 数据库优化? 主从 如何读写分离 如何设计表,如日增百万 sql的执行步骤 如何查看索引被...

  • sql优化

    参考:数据库SQL优化大总结之 百万级数据库优化方案如何优化MySQL千万级大表,我写了6000字的解读 --很棒...

网友评论

    本文标题:表设计、sql、应用层-简单实用的数据库优化建议

    本文链接:https://www.haomeiwen.com/subject/birnxftx.html