SQL Server 海量数据查询代码优化以及建议

1.应尽量避免在  where  子句中对字段进行   null  值推断,否则将导致引擎放弃使用索引而进

行全表扫描,如:

select id from t where num is null

能够在num 上设置默认值0 ,确保表中num 列没有null 值,然后这样查询:

select id from t where num=0

2.应尽量避免在  where  子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫

描。优化器将无法通过索引来确定将要命中的行数, 因此须要搜索该表的全部行。

3.应尽量避免在  where  子句中使用  or  来连接条件。否则将导致引擎放弃使用索引而进行

全表扫描,如:

select id from t where num=10 or num=20

能够这样查询:

select id from t where num=10

union all

select id from t where num=20

4.in  和  not in  也要慎用,由于IN 会使系统无法使用索引,而仅仅能直接搜索表中的数据。如:

select id from t where num in(1,2,3)

对于连续的数值。能用   between  就不要用  in  了:

select id from t where num between 1 and 3

5.尽量避免在索引过的字符数据中,使用非打头字母搜索。

这也使得引擎无法利用索引。

见例如以下样例:

SELECT * FROM T1 WHERE NAME LIKE ‘%L%’

SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’

SELECT * FROM T1 WHERE NAME LIKE ‘L%’

即使 NAME  字段建有索引。前两个查询依旧无法利用索引完毕加快操作,引擎不得不正确全

表全部数据逐条操作来完毕任务。而第三个查询可以使用索引来加快操作。

6.必要时强制查询优化器使用某个索引。如在  where  子句中使用參数,也会导致全表扫描。

由于 SQL       仅仅有在执行时才会解析局部变量,但优化程序不能将訪问计划的选择推迟到执行

时;它必须在编译时进行选择。然  而。假设在编译时建立訪问计划,变量的值还是未知的。

因而无法作为索引选择的输入项。如以下语句将进行全表扫描:

select id from t where [email protected]

能够改为强制查询使用索引:

select id from t with(index(索引名)) where [email protected]

7.应尽量避免在  where  子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行

全表扫描。如:

SELECT * FROM T1 WHERE F1/2=100

应改为:

SELECT * FROM T1 WHERE F1=100*2

SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’

应改为:

SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’

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())

即:不论什么对列的操作都将导致表扫描,它包含数据库函数、计算表达式等等,查询时要尽可

能将操作移至等号右边。

8.应尽量避免在where 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表

扫描。如:

select id from t where substring(name,1,3)=‘abc‘--name 以abc 开头的id

select id from t where datediff(day,createdate,‘2005-11-30‘)=0--           ‘2005-11-30 ’生成的id

应改为:

select id from t where name like ‘abc%‘

select id from t where createdate>=‘2005-11-30‘ and createdate<‘2005-12-1‘

9.不要在  where  子句中的“= ”左边进行函数、算术运算或其它表达式运算,否则系统将可

能无法正确使用索引。

10.在使用索引字段作为条件时。假设该索引是复合索引。那么必须使用到该索引中的第一

个字段作为条件时才干保证系统使用该索引,否则该索引将不会被使用。而且应尽可能的让

字段顺序与索引顺序相一致。

11.非常多时候用  exists 是一个好的选择:

select num from a where num in(select num from b)

用以下的语句替换:

select num from a where exists(select 1 from b where num=a.num)

SELECT SUM(T1.C1)FROM T1 WHERE(

(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)

SELECT SUM(T1.C1) FROM T1WHERE EXISTS(

SELECT * FROM T2 WHERE T2.C2=T1.C2)

两者产生同样的结果,可是后者的效率显然要高于前者。由于后者不会产生大量锁定的表扫

描或是索引扫描。

假设你想校验表里是否存在某条纪录,不要用count(*)那样效率非常低。并且浪费server资源。

能够用EXISTS 取代。如:

IF (SELECT COUNT(*) FROM table_name WHERE column_name = ‘xxx‘)

能够写成:

IF EXISTS (SELECT * FROM table_name WHERE column_name = ‘xxx‘)

常常须要写一个T_SQL 语句比較一个父结果集和子结果集。从而找到是否存在在父结果集中

有而在子结果集中没有的记录,如:

SELECT a.hdr_key FROM hdr_tbl a---- tbl a  表示tbl 用别名a 取代

WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)

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

SELECT hdr_key FROM hdr_tbl

WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)

三种写法都能够得到相同正确的结果,可是效率依次减少。

12.尽量使用表变量来取代暂时表。假设表变量包括大量数据,请注意索引很有限(仅仅有

主键索引)。

13.避免频繁创建和删除暂时表。以降低系统表资源的消耗。

14.暂时表并非不可使用。适当地使用它们能够使某些例程更有效,比如。当须要反复引

用大型表或经常使用表中的某个数据集时。可是。对于一次性事件,最好使用导出表。

15.在新建暂时表时。假设一次性插入数据量非常大,那么能够使用  select  into  取代   create

table ,避免造成大量   log  ,以提快速度;假设数据量不大。为了缓和系统表的资源,应先

create table。然后insert。

16.假设使用到了暂时表,在存储过程的最后务必将全部的暂时表显式删除,先  truncate

table   ,然后  drop table  ,这样能够避免系统表的较长时间锁定。

17.在全部的存储过程和触发器的開始处设置   SET   NOCOUNT   ON   ,在结束时设置   SET

NOCOUNT OFF  。

无需在运行存储过程和触发器的每一个语句后向client发送   DONE_IN_PROC

消息。

18.尽量避免大事务操作。提高系统并发能力。

19.尽量避免向client返回大数据量,若数据量过大,应该考虑对应需求是否合理。

20.  避免使用不兼容的数据类型。比如float 和int、char 和varchar 、binary 和varbinary 是不

兼容的。

数据类型的不兼容可能使优化器无法运行一些本来能够进行的优化操作。比如:

SELECT name FROM employee WHERE salary > 60000

在这条语句中,如salary 字段是money 型的,则优化器非常难对其进行优化, 由于60000 是个整型

数。我们应当在编程时将整型转化成为钱币型,而不要等到执行时转化。

21.充分利用连接条件。在某种情况下。两个表之间可能不仅仅一个的连接条件。这时在  WHERE

子句中将连接条件完整的写上,有可能大大提高查询速度。

例:

SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO

SELECT  SUM(A.AMOUNT)  FROM  ACCOUNT  A,CARD  B  WHERE  A.CARD_NO  =  B.CARD_NO  AND

A.ACCOUNT_NO=B.ACCOUNT_NO

第二句将比第一句运行快得多。

22、使用视图加速查询

把表的一个子集进行排序并创建视图,有时能加速查询。它有助于避免多重排序  操作。而

且在其它方面还能简化优化器的工作。

比如:

SELECT cust.name,rcvbles.balance,??other columns

FROM cust。rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

AND cust.postcode>“98000”

ORDER BY cust.name

假设这个查询要被运行多次而不止一次,能够把全部未付款的客户找出来放在一个视图中,

并按客户的名字进行排序:

CREATE VIEW DBO.V_CUST_RCVLBES

AS

SELECT cust.name,rcvbles.balance,??other columns

FROM cust。rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

ORDER BY cust.name

然后以以下的方式在视图中查询:

SELECT   *   FROM V_CUST_RCVLBES

WHERE postcode>“98000”

视图中的行要比主表中的行少,并且物理顺序就是所要求的顺序,降低了磁盘I/O,所以查

询工作量能够得到大幅降低。

23、能用DISTINCT 的就不用GROUP BY

SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID

可改为:

SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10

24.能用UNION ALL 就不要用UNION

UNION ALL 不运行SELECT DISTINCT 函数,这样就会降低非常多不必要的资源

25.尽量不要用SELECT INTO 语句。

SELECT INOT  语句会导致表锁定。阻止其它用户訪问该表。

上面我们提到的是一些主要的提高查询速度的注意事项,可是在很多其它的情况下,往往须要重复

试验比較不同的语句以得到最佳方案。最好的方法当然是測试,看实现  同样功能的SQL 语

句哪个运行时间最少。可是数据库中假设数据量非常少,是比較不出来的。这时能够用查看执

行计划,即:把实现同样功能的多条SQL 语句考到  查询分析器,按CTRL+L 看查所利用的索

引,表扫描次数(这两个对性能影响最大),整体上看询成本百分比就可以。

时间: 2024-10-13 12:46:24

SQL Server 海量数据查询代码优化以及建议的相关文章

SQL Server海量数据查询代码优化建议

1.尽量避免在WHERE子句中对字段进行NULL值判断 在WHERE子句中对字段进行NULL值判断会导致引擎放弃使用索引而进行全表扫描.如: SELECT id FROM t WHERE num IS NULL 可以在num字段设置默认值0,确保表中 num字段没有NULL值,然后这样查询: SELECT id FROM t WHERE num=0 2.尽量避免在WHERE子句中使用!=或<>操作符 在WHERE子句中使用!=或<>操作符将导致引擎放弃使用索引而进行全表扫描.优化器

Sql Server参数化查询之where in和like实现详解

来自:http://www.cnblogs.com/lzrabbit/archive/2012/04/22/2465313.html#wherein 文章导读 拼SQL实现where in查询 使用CHARINDEX或like实现where in 参数化 使用exec动态执行SQl实现where in 参数化 为每一个参数生成一个参数实现where in 参数化 使用临时表实现where in 参数化 like参数化查询 xml和DataTable传参  身为一名小小的程序猿,在日常开发中不可以

【转载】Sql Server参数化查询之where in和like实现详解

文章导读 拼SQL实现where in查询 使用CHARINDEX或like实现where in 参数化 使用exec动态执行SQl实现where in 参数化 为每一个参数生成一个参数实现where in 参数化 使用临时表实现where in 参数化 like参数化查询 xml和DataTable传参  身为一名小小的程序猿,在日常开发中不可以避免的要和where in和like打交道,在大多数情况下我们传的参数不多简单做下单引号.敏感字符转义之后就直接拼进了SQL,执行查询,搞定.若有一天

转载 50种方法优化SQL Server数据库查询

原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷

【转】Sql Server参数化查询之where in和like实现详解

转载至:http://www.cnblogs.com/lzrabbit/archive/2012/04/22/2465313.html 文章导读 拼SQL实现where in查询 使用CHARINDEX或like实现where in 参数化 使用exec动态执行SQl实现where in 参数化 为每一个参数生成一个参数实现where in 参数化 使用临时表实现where in 参数化 like参数化查询 xml和DataTable传参  身为一名小小的程序猿,在日常开发中不可以避免的要和wh

【转】Sql Server参数化查询之where in和like实现之xml和DataTable传参

转载至: http://www.cnblogs.com/lzrabbit/archive/2012/04/29/2475427.html 在上一篇Sql Server参数化查询之where in和like实现详解中介绍了在Sql Server使用参数化查询where in的几种实现方案,遗漏了xml和表值参数,这里做一个补充 文章导读 方案5使用xml参数 方案6 使用表值参数TVP,DataTable传参 6种实现方案总结 方案5 使用xml参数 对sql server xml类型参数不熟悉的

sql server 阻塞查询

原文:sql server 阻塞查询 在生产环境下,有时公司客服反映网页半天打不到,除了在浏览器按F12的Network响应来排查,确定web服务器无故障后.就需要检查数据库是否有出现阻塞 当时数据库的生产环境中主表数据量超过2000w,子表数据量超过1亿,且更新和新增频繁.再加上做了同步镜像,很消耗资源. 这时就要新建一个会话,大概需要了解以下几点: 1.当前活动会话量有多少? 2.会话运行时间? 3.会话之间有没有阻塞? 4.阻塞时间 ? 查询阻塞的方法有很多.有sql 2000 的sp_l

在 SQL Server 中查询EXCEL 表中的数据遇到的各种问题

原文:在 SQL Server 中查询EXCEL 表中的数据遇到的各种问题 SELECT * FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0','Data Source="D:\KK.xls";User ID=Admin;Password=;Extended properties=Excel 5.0')...[Sheet1$] 问题: 消息 15281,级别 16,状态 1,第 1 行 SQL Server 阻止了对组件 'Ad Hoc Di

SQL Server中查询用户的对象权限和角色的方法

--SQL Server中查询用户的对象权限和角色的方法 -- 查询用户的object权限 exec sp_helprotect NULL, 'sa' -- 查询用户拥有的role exec sp_helpuser 'public' -- 查询哪些用户拥有指定的系统role exec sp_helpsrvrolemember 'sysadmin' -- 可查询嵌套role WITH tree_roles as ( SELECT role_principal_id, member_principa