您的位置:首页 > 数据库

SQL性能优化整合持续更新

2017-12-26 23:26 405 查看
    性能优化是面试、程序员之间交流的重要话题。数据到了一定量级后和用户达到一定数量频繁的请求某些数据查询等操作表,数据库是成为优化的必经之路。众说纷纭,打算从表设计到查询、业务操作等方面入手。数据库从设计到编码到使用这些过程中,及早发现问题比到后面使用后找到问题付出的代价要小,随着时间的发展,越晚发现问题付出的代价越大。

设计表结构时优化:

1)一般来说,sql的三大范式可以解决一部分的性能问题。印象最深刻的是从业的第一家公司,一张分组表把人员用一个nvarchar(max)保存的,人员要退票啊、买票出错修改信息、查询一个人在这次活动拥有几种票等操作中必须要拆分这个字段,所以当时数据达到一定量级,要么重新设计表,要么。。。我写了个split函数=.=虽然可以完美操作并且解决这些问题,但是操作这张表的时候性能损耗太多了,有时候会出现数据脏读的一些问题,最后还是重新设计表。花了很长时间整理这些数据,得不偿失。当然必要时能够优化性能的不满足三大范式确实是可以的。

第1规范:没有重复的组或多值的列,这是数据库设计的最低要求。

第2规范: 每个非关键字段必须依赖于主关键字,不能依赖于一个组合式主关键字的某些组成部分。消除部分依赖,大部分情况下,数据库设计都应该达到第二范式。

第3规范: 一个非关键字段不能依赖于另一个非关键字段。消除传递依赖,达到第三范式应该是系统中大部分表的要求,除非一些特殊作用的表。

2)字段设计的时候,一定要注意字段范围,能用int类型的就不要使用varchar、nvarchar。text和img这些应该在高版本没有了吧,慎重使用。就算要用,把他们用txt文件或者xml文件存到服务器,数据库存链接就好。尽量满足现在以后的数据长度。数据保存的时候尽量给默认值,因为查询的时候要排除null,少一个查询条件多一点速度。尽量减少自增字段,不利于数据迁移和并发量高等一些数据操作

2)表与表之间尽量避免数据冗余。有这么一个场景,用户信息表,用户发邮件表。要求:查看该用户的发邮件记录并且把昵称显示出来,用户表里面有个昵称,但是为了方便,某程序员在邮件表加了个昵称,然后一条sql搞定。问题:当用户换昵称的时候这个邮件表怎么显示?有人会说,用触发器啊主表改变从表也变化呀。这样确实可以实现改动,但是如果很多表都跟这个昵称有关呢,是不是在触发器里面写很多个update。。。万一触发器出错了呢?所以,不能偷懒绝不偷懒,除非这个昵称数据不会变动,那样确实是可以事半功倍。

3)尽量少使用表删除更新联动。这个举个小例子吧,同样是商品表和价格表和规格表,一个商品多个规格,一个规格多个价格,一个管理员修改一件商品的价格,一个管理员同时删除这个规格。这个表炸了=.=而且系统出错也不知道是哪里出错,跟约束和触发器报错一样的。

4)合理使用触发器,触发器的使用完全是为了数据的完整性,用得合理事半功倍,而且还是个多线程操作

5)合理使用索引,索引像个目录一样,其数据结构是树,查询速度也是很可观的。前期数据量少的时候感觉不出来,数据量一大起来,真的可以为所欲为。当然索引不是越多越好,合理就行

关于索引的选择,应改主意:

根据数据量决定哪些表需要增加索引,数据量小的可以只选择主键。

根据使用频率决定哪些字段需要建立索引,选择经常作为连接条件、筛选条件、聚合查询、排序的字段作为索引的候选字段。

把经常一起出现的字段组合在一起,组成组合索引,组合索引的字段顺序与主键一样,也需要把最常用的字段放在前面,把重复率低的字段放在前面。

一个表不要加太多索引,因为索引影响插入和更新的速度。

6)如果考虑数据库与项目服务器分离的时候尽量考虑硬件的内存带宽和硬盘存储量

7)当然主外键尽量少使用联合主键或者外键,查询数据的时候少一个条件也是一种速度的提升,也听说过查询速度跟联合主键的位置也有一定的关系,这个正在考证。

业务操作方面优化(这里只讲查询优化):

1)尽量少使用select *,勤快点用select a,b,c。。。

2)避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序

3)select a这个a尽量少使用字符串转时间啊,需要要计算呐,判断呀,字符拼接等一些操作。一个两个没啥,多了真的是绑了几个铅块。当然必要合理不得已等情况下

4)统计select count(a)、select count(*)建议用select count(1)

5)where后面尽量少用 null判断,前面讲过尽量给默认值

6)where查询的时候尽量避免索引字段的类型转换、使用函数、数值计算或字符拼接。因为表频繁删除新增等操作索引有空缺,这些操作会给查询带来很重的负担

7)避免多级的嵌套查询:select (select count(1)from A)as a from (select * from (select a from a where))inner join ...

8)避免使用子查询,having、in。。能用exists代替的、能用join等连接查询代替的就代替吧。having和in真的是性能油老虎,全局反复查询

9)在连接查询条件里面能完成的,尽量不要到where里面去筛选,这样两次全局查询很吃性能

10)避免使用行转列操作,经常发现很多小伙伴做统计的时候脑袋都要炸了。。。我有个办法,sql最好保存统计信息或者后端保存xml格式的统计信息,定时执行统计操作,把数据保存起来,尤其是这个统计信息操作比较频繁的时候。很有效果

11)数据库操作时,尽量不用游标,能用循环或者CASE WHEN转换的尽量吧。

12)存储过程如果执行步骤比较多,操作的表比较多,建议在后端分部分解决,容易导致数据的脏读等一些问题

13)适当的使用视图

     总结:可能还有很多没有完善,希望得到大家的评价来完善这个话题。

               总的来说,数据库的优化,从设计就应该开始,找到问题减少以后发现问题执行的时间效率。优化应该要配合web、后端、数据库、硬件这些方面来实施,甚至nosql,数据库分布式,数据库缓存等一些有效的方法提高数据访问速度,提高用户的使用效率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sql 性能优化