1.3.7 系统设计
➢ 整个系统的设计特别是系统结构设计对性能是有很大影响的,对于一般的 OLTP 系统,可以选择 CS 结构、三层的 CS 结
构等,不同的系统结构其性能的关键也有所不同。
➢ 系统设计阶段应该归纳一些业务逻辑放在数据库编程实现,数据库编程包括数据库存储过程、触发器和函数。用数据
库编程实现业务逻辑的好处是减少网络流量并可更充分利用数据库的预编译和缓存功能。
1.3.8 索引的设计
在设计阶段,可以根据功能和性能的需求进行初步的索引设计,这里需要根据预计的数据量和查询来设计索引,可
能与将来实际使用的时候会有所区别。
关于索引的选择,应改主意:
➢ 根据数据量决定哪些表需要增加索引,数据量小的可以只有主键。
➢ 根据使用频率决定哪些字段需要建立索引,选择经常作为连接条件、筛选条件、聚合查询、排序的字段作为索引的候
选字段。
➢ 把经常一起出现的字段组合在一起,组成组合索引,组合索引的字段顺序与主键一样,也需要把最常用的字段放在前
面,把重复率低的字段放在前面。
➢ 一个表不要加太多索引,因为索引影响插入和更新的速度。
1.4 编码阶段
编码阶段是本文的重点,因为在设计确定的情况下,编码的质量几乎决定了整个系统的质量。
编码阶段首先是需要所有程序员有性能意识,也就是在实现功能同时有考虑性能的思想,数据库是能进行集合运算
的工具,我们应该尽量的利用这个工具,所谓集合运算实际是批量运算,就是尽量减少在客户端进行大数据量的循环操作,
而用 SQL 语句或者存储过程代替。关于思想和意识,很难说得很清楚,需要在编程过程中来体会。
下面罗列一些编程阶段需要注意的事项:
1.4.1 只返回需要的数据
返回数据到客户端至少需要数据库提取数据、网络传输数据、客户端接收数据以及客户端处理数据等环节,如果返回
不需要的数据,就会增加服务器、网络和客户端的无效劳动,其害处是显而易见的,避免这类事件需要注意:
➢ 横向来看,不要写 SELECT 的语句,而是选择你需要的字段。
➢ 纵向来看,合理写 WHERE 子句,不要写没有 WHERE 的 SQL 语句。
➢ 注意 SELECT INTO 后的 WHERE 子句,因为 SELECT INTO 把数据插入到临时表,这个过程会锁定一些系统表,如果这个
WHERE 子句返回的数据过多或者速度太慢,会造成系统表长期锁定,诸塞其他进程。
➢ 对于聚合查询,可以用 HAVING 子句进一步限定返回的行。
1.4.2 尽量少做重复的工作
这一点和上一点的目的是一样的,就是尽量减少无效工作,但是这一点的侧重点在客户端程序,需要注意的如下:
➢ 控制同一语句的多次执行,特别是一些基础数据的多次执行是很多程序员很少注意的。
➢ 减少多次的数据转换,也许需要数据转换是设计的问题,但是减少次数是程序员可以做到的。
➢ 杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。
➢ 合并对同一表同一条件的多次 UPDATE,比如
UPDATE EMPLOYEE SET FNAME=’HAIWER’ WHERE EMP_ID=’ VPA30890F’ UPDATE EMPLOYEE SET LNAME=’YANG’ WHERE EMP_ID=’
VPA30890F’ 这两个语句应该合并成以下一个语句 UPDATE EMPLOYEE SET FNAME=’HAIWER’,LNAME=’YANG’ WHERE
EMP_ID=’ VPA30890F’
➢ UPDATE 操作不要拆成 DELETE 操作 INSERT 操作的形式,虽然功能相同,但是性能差别是很大的。
➢ 不要写一些没有意义的查询,比如 SELECT FROM EMPLOYEE WHERE 1=2
1.4.3 注意事务和锁
事务是数据库应用中和重要的工具,它有原子性、一致性、隔离性、持久性这四个属性,很多操作我们都需要利用事
务来保证数据的正确性。在使用事务中我们需要做到尽量避免死锁、尽量减少阻塞。具体以下方面需要特别注意:
➢ 事务操作过程要尽量小,能拆分的事务要拆分开来。
➢ 事务操作过程不应该有交互,因为交互等待的时候,事务并未结束,可能锁定了很多资源。
➢ 事务操作过程要按同一顺序访问对象。
➢ 提高事务中每个语句的效率,利用索引和其他方法提高每个语句的效率可以有效地减少整个事务的执行时间。
➢ 尽量不要指定锁类型和索引,SQL SERVER 允许我们自己指定语句使用的锁类型和索引,但是一般情况下,SQL SERVER
优化器选择的锁类型和索引是在当前数据量和查询条件下是最优的,我们指定的可能只是在目前情况下更有,但是数
据量和数据分布在将来是会变化的。
➢ 查询时可以用较低的隔离级别,特别是报表查询的时候,可以选择最低的隔离级别(未提交读)。