200 likes | 378 Views
Sql 效率经验总结. SQL 开发观点. 对于客户 - 服务器结构的数据库应用程序来说,减少网络传输的数据量直接影响到应用程序的性能。在编程时应注意尽量减少网络流量,避免不必要的数据传输。另外,数据库的加锁机制和事务处理也会直接影响到一个应用程序性能的好坏。在这里提供一些建议供大家参考。. 合理使用 存储过程. 将完成一个功能的 SQL 语句写成存储过程,不但可以减少网络流量,而且由于存储过程是预编译的,能进一步提高响应速度。. WHERE 子句. 在 SELECT 语句中通过使用 WHERE 子句来减少返回的记录数。. 去掉不需要的字段.
E N D
SQL 开发观点 • 对于客户-服务器结构的数据库应用程序来说,减少网络传输的数据量直接影响到应用程序的性能。在编程时应注意尽量减少网络流量,避免不必要的数据传输。另外,数据库的加锁机制和事务处理也会直接影响到一个应用程序性能的好坏。在这里提供一些建议供大家参考。
合理使用存储过程 将完成一个功能的SQL语句写成存储过程,不但可以减少网络流量,而且由于存储过程是预编译的,能进一步提高响应速度。
WHERE子句 在SELECT语句中通过使用WHERE子句来减少返回的记录数。
去掉不需要的字段 避免使用 SELECT * FROM 语句,要使用 SELECT F1,F2 FROM 语句,去掉不需要的字段。
避免显式或隐含的类型转换 避免显式或隐含的类型转换,如在WHERE 子句中Numeric 型和 Int型的列的比较。
SQL SERVER 在SELECT 语句中,如果表中的大部分记录符合查询条件,尽管WHERE子句中的字段上有索引,但SQL SERVER不会使用索引,而是顺序扫描该表。
复合索引 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在WHERE 或ORDER BY子句中这些字段出现的顺序要与建立索引时的字段顺序一致,可以是F1或F1,F2 或F1,F2,F3。否则SQL SERVER不会用到该索引。
尽快地提交事务 SQL SERVER为了支持事务一致性,对共享的资源上保留锁直至事务被提交。其他要使用相同资源的用户必须要等待。如果一个事务变长的话,锁的队列以及等待锁的用户队列将会变长,这最终导致系统吞吐量的降低。长的事务还增加了出现死锁的可能性。具体包括在事务中不能包含用户交互,避免更新同一数据两次,大批量的数据更新放在事物的后面部分等。
尽量减少对列的四则运算 • 在WHERE 子句中,尽量减少对列的四则运算。 例如: select colAfrom tableAwhere salary * 12 > 12000 • 应该用如下语句代替: select colAfrom tableAwhere salary > 1000 • 在WHERE 子句中,尽量用>= 代替>。例如: select F1 from Table1 where a>3 (其中a 为int 型) • 在该例中,a列上是有索引的,SQL SERVER扫描索引页,直到a=3的页,然后顺序扫描,直到a=4,如果a=3的记录很多,会有很多无效的I/O操作。 • 应该用如下语句代替:elect F1 from Table1 where a>=4
避免在IF EXISTS 和 IN 操作符中使用NOT • 因为不使用NOT,SQL SERVER在得到满足条件的第一条记录后返回,而使用NOT操作符,SQL SERVER 可能要扫描整个表。例如: if not exists (select * from tableA where…) begin statement group one end else begin statement group two end • 应该用如下语句代替: if exists (select * from tableA where…) begin statement group two end else begin statement group one end
IF EXISTS 语句 • 在判断有无符合条件的记录时不要用SELECT COUNT (*) 语句,而是要用IF EXISTS 语句: 例如: declare @var int select @var = count(*)from employeewhere emp_id = 123 if @var != 0 ... more sql code ... • 应该用如下语句代替: if exists (select 1 from employee where emp_id = 123) begin ... more sql code ... end
WHERE子句中的等于列(1) • 在WHERE子句中如果对于某列有等于的条件,则在SELECT子句中不应该出现该列, 例如: select cust_number, cust_name from customerwhere cust_number = 612 • 应该用如下语句代替: select cust_name from customerwhere cust_number = 612
WHERE子句中的等于列(2) • 在WHERE子句中如果对于某列有等于的条件,则在ORDER BY子句中不应该出现该列, 例如: select cust_number, cust_name, cust_st from customerwhere cust_st = ‘L’ order by cust_st, cust_name 应该用如下语句代替: select cust_number, cust_name from customerwhere cust_st = ‘L’ order by cust_number
同一个列的多个OR条件 • 在WHERE子句中,对于同一个列的多个OR条件,用IN 操作符来代替, 例如: select cust_number, cust_name, cust_st from customer where cust_st = ‘L’ or cust_st = ‘A’ or cust_st = ‘I’ order by cust_st, cust_number • 应该为: select cust_number, cust_name , cust_st from customer where cust_st in (‘L’, ‘A’, ‘I’) order by cust_st, cust_number
求最大值和最小值的列 • 对于要求最大值和最小值的列,如果在该列上有索引,则要分开用两个SQL语句来求, • 例如: select max(price), min(price) from titles (price上有索引) • 应该用如下语句代替: select max(price) from titles select min(price) from titles
对于能用联结实现的功能,不要用子查询实现 例如: select name from customer where customer_id in ( select customer_id from order where money>1000) • 应该用如下语句代替: select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100
检查被更新的行数时 • 在检查被更新的行数时用@@rowcount,而不用select count(*). 例如: select count(*) from customer where cust_st = ‘1’ and cust_code = ‘2’ update customer set cust_discount = .15 where cust_st =’1’ and cust_code = ‘2’ • 应该用如下语句代替: update customer set cust_discount = .15 where cust_st = ‘1’ and cust_code = ‘2’ select @update_count = @@rowcount
通配符”_”的使用 • 对于通配符”_”的使用,如果该通配符放在匹配模式的前面,将引起SQL引擎对表进行扫描,而不使用索引。 例如: select Ven_ID from vendor where name like ‘_a’ • 如有可能,可用如下语句代替: select Ven_ID from vendor where name like ‘[a-z]a’