怎么样写SQL语句可以提高数据库的执行速度?应该注意那些?

2024-11-22 21:45:18
推荐回答(2个)
回答1:

这个范围太大了,一下子是很难说清楚的,如果用sql server 的话,可以使用它自带的优化器来优化,然后看看它给你的建议去优化。要注意规范化编程。而且要抓住一个原则来写,就是进可能缩小查询出来的结果集,哪怕多次查询都没所谓,要一步一步把大数据量缩小。很多只是还是得在时间中优化。SET STATISTICS TIME ON;SQL 语句SET STATISTICS TIME OFF;这个是sqlserver ,可以测出执行时间。编写的时候要时刻想着:缩小结果集、减少连接次数和表数。大数据量不要用update,可以用临时表作为过度来实现update操作。

回答2:

T-SQL脚本优化技巧:
1)对于SELECT/UPDATE语句必须显示的定义所有的列,避免使用星号。
2)在执行SELECT/INSERT/UPDATE/DELETE语句时,请考虑执行规划的重用,尽量考虑用SP-EXECUTESQL存储过程。
3)优先使用 SELECT...INTO,然后使用 INSERT...SELECT,以避免大量死锁。
4)如果需要删除所有的数据,用TRUNCATE TABLE 代替DELETE 。
5)避免使用DISTINCT 语句。
6)如果你需要有限的记录,通过TOP N代替SET ROWCOUNT来控制排序取值。
7)避免使用SARGABLE的语句在WHERE子句,比如: OR, <>, !=, !<, >!, IS NULL, NOT, NOT IN, NOT LIKE 和LIKE,因为这些操作很难利用已知的索引。
8)避免使用NOT IN,可以采用IN,EXISTS NOT EXISTS和LEFT JOIN 加空值判断
--NOT EXISTS, 效率最高 SELECT a.hdr_key
FROM hdr_tbl a
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key) --LEFT JOIN SELECT a.hdr_key
FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key
WHERE b.hdr_key IS NULL --NOT IN ,效率最低 SELECT hdr_key
FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl) 9)使用EXISTS判断记录是否存在。
--不好的写法: IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx') --正确的写法: IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx') 10)避免在GROUP BY中使用HAVING 语句。
11)GROUP BY的语句要尽量简单,不要进行GROUP BY语句的嵌套,避免在GROUP BY中包含多余的列
考虑在GROUP BY的列,进行ORDER BY排序,特别在多用户的环境下。
12)如果需要在一个包含JOIN的SELECT语句进行GROUP BY,请考虑用子查询代替JOIN. 如果必须使用GROUP BY, GROUP BY 的应该列在同一张表。
13)如果WHERE条件语句有多个AND条件,请确保至少有一个列有索引,如果没有可以建立多列复合INDEX。
14)对于SQL 无法执行自动优化的WHERE条件语句,可以通过HINTS显示的制定INDEX来提高查询的效率。
--可能不好的写法: SELECT * FROM tblTaskProcessesWHERE nextprocess = 1 AND processid IN (8,32,45) --正确的写法: SELECT * FROM tblTaskProcesses (INDEX = IX_ProcessID)WHERE nextprocess = 1 AND processid IN (8,32,45) 15)尽可能避免在WHERE条件语句中使用函数计算。
--不好的写法: WHERE SUBSTRING(firstname,1,1) = 'm' --正确的写法: WHERE firstname like 'm%' 16)在WHERE条件语句中,避免在函数中包列,如果无法避免,请考虑在该列建立INDEX。
--不好的写法: SELECT member_number, first_name, last_name
FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21 -- 正确的写法: SELECT member_number, first_name, last_name
FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE()) 17)在WHERE条件语句中,避免使用NOT 。
--不好的写法: WHERE NOT column_name > 5 --正确的写法: WHERE column_name <= 5 18)在WHERE条件语句中,推荐使用10位的日期函数。
--正确的写法: SELECT * FROM Northwind.dbo.Orders WHERE OrderDate > '12/31/1997'--不好的写法: SELECT * FROM Northwind.dbo.Orders WHERE OrderDate > '12/31/97' 19)避免使用UNION,而是用UNION ALL 。
20)使用 SQL-92 标准连接句法,为了提高性能,应优先使用连接,然后使用子查询或嵌套查询,表之间的连接使用INNER JOIN,LEFT JOIN 和RIGHT JOIN,不使用CROSS JOIN和多列表方式.。
21)多表关联避免超过5个,可以通过临时表(表变量),简化复杂的关联。

存储过程的开发和优化技巧:1)避免使用触发器TRIGGER,考虑用存储过程代替触发器
——与临时表一样,光标并不是不可使用。对小型数据集使用FAST_FORWARD 光标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用光标执行的速度快。如果开发时 间允许,基于光标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。2)考虑用UDF代替存储过程
——使用表值 UDF 时要小心,因为在变量(而不是常量)中传递某个参数时,如果在 WHERE 子句中使用该参数,会导致表扫描。还要避免在一个查询中多次使用相同的表值 UDF。但是,表值 UDF 确实具有某些非常方便的动态编译功能。3)对于频繁调用的存储过程,考虑用SP_RECOMPILE重新编译
4)使用输出语句代替返回整个数据集,输出语句的执行效率会更加高效
5)在存储过程的头部使用SET NOCOUNT ON, 通过@@ROWCOUNT来控制,这样可以减少网络流量和避免潜在的问题, 而在结束时设置 SET NOCOUNT OFF.
6)不使用SP_作为存储过程的名称,建议用USP_,这个会影响数据库的执行时间.
7)尽可能使用临时表而使用表变量,表变量可以减少上锁和重新编译的次数并且表变量不使用TEMPDB的空间,而是全部使用内存来处理数据.
8)先在例程中创建临时表,最后再显式删除临时表。将 DDL 与 DML 语句混合使用有助于处理额外的重新编译活动
9)尽可能不要在流程控制语句中使用临时表,比如:IF .. ELSE, WHILE
10)避免在事务中进行赋值和复杂计算,

--不好的写法: Create procedure proc_1 As Begin Begin transaction -- step 1 verify the data -- step 2 perform calculations -- step 3 get default variable values (date, user info) -- update/insert records commit end --不好的写法: Create procedure proc_1 As Begin -- step 1 verify the data -- step 2 make calculations -- step 3 get default variable values (date, user info) Begin transaction -- update/insert records commit end 上面的一些优化规则只是一般原则,在某些特殊情况下可能会有所差别,如果需要分析T-SQL的性能,可以通过查询分析器的CTRL+L 显示执行规划进行分析,也可以通过 SET STATISTICS PROFILE ON进行分析.