本文转载:
http://blog.csdn.net/gprime/article/details/1687930
人
们
在使用
SQL
时
往往会陷入一个
误
区,即太
关
注于所得的
结
果是否正确,而忽略了不同的
实现
方法之
间
可能存在的性能差异,
这种
性能差异在大型的或是
复杂
的数据
库环
境中(如
联
机事
务处
理
OLTP
或决策支持系
统
DSS
)中表
现
得尤
为
明
显
。
笔者在工作
实
践中
发现
,不良的
SQL
往往来自于不恰当的索引
设计
、不充份的
连
接条件和不可
优
化的
where
子句。
在
对
它
们进
行适当的
优
化后,其运行速度有了明
显
地提高!
下面我将从
这
三个方面分
别进
行
总结
:
为
了更直
观
地
说
明
问题
,所有
实
例中的
SQL
运行
时间
均
经过测试
,不超
过
1秒的均表示
为
(
< 1
秒)。
----
测试环
境
:
主机:
HP LH II----
主
频
:
330MHZ----
内存:
128
兆
----
操作系
统
:
Operserver5.0.4----
数据
库
:
Sybase11.0.3
一、不合理的索引
设计
----
例:表
record
有
620000
行,
试
看在不同的索引下,下面几个
SQL
的运行情况:
---- 1.
在
date
上建有一非个群集索引
select count(*) from record where date >'19991201' and date < '19991214'and amount >2000 (25
秒
)
select date ,sum(amount) from record group by date(55
秒
)
select count(*) from record where date >'19990901' and place in ('BJ','SH') (27
秒
)
----
分析:
----
date
上有大量的重
复值
,在非群集索引下,数据在物理上随机存放在数据
页
上,在范
围查
找
时
,必
须执
行一次表
扫
描才能找到
这
一范
围
内的全部行。
---- 2.
在
date
上的一个群集索引
select count(*) from record where date >'19991201' and date < '19991214' and amount >2000
(
14
秒)
select date,sum(amount) from record group by date
(
28
秒)
select count(*) from record where date >'19990901' and place in ('BJ','SH')
(
14
秒)
----
分析:
----
在群集索引下,数据在物理上按
顺
序在数据
页
上,重
复值
也排列在一起,因而在范
围查
找
时
,可以先找到
这
个范
围
的起末点,且只在
这
个范
围
内
扫
描数据
页
,避免了大范
围扫
描,提高了
查询
速度。
---- 3.
在
place
,
date
,
amount
上的
组
合索引
select count(*) from record where date >'19991201' and date < '19991214' and amount >2000
(
26
秒)
select date,sum(amount) from record group by date
(
27
秒)
select count(*) from record where date >'19990901' and place in ('BJ, 'SH')
(
< 1
秒)
----
分析:
----
这
是一个不很合理的
组
合索引,因
为
它的前
导
列是
place
,第一和第二条
SQL
没有引用
place
,因此也没有利用上索引;第三个
SQL
使用了
place
,且引用的所有列都包含在
组
合索引中,形成了索引覆盖,所以它的速度是非常快的。
---- 4.
在
date
,
place
,
amount
上的
组
合索引
select count(*) from record where date >'19991201' and date < '19991214' and amount >2000(< 1
秒
)
select date,sum(amount) from record group by date
(
11
秒)
select count(*) from record where date >'19990901' and place in ('BJ','SH')
(
< 1
秒)
----
分析:
----
这
是一个合理的
组
合索引。它将
date
作
为
前
导
列,使
每
个
SQL
都可以利用索引,并且在第一和第三个
SQL
中形成了索引覆盖,因而性能达到了最
优
。
---- 5.
总结
:
----
缺省情况下建立的索引是非群集索引,但有
时
它并不是最佳的;合理的索引
设计
要建立在
对
各
种查询
的分析和
预测
上。
一般来
说
:
①
.
有大量重
复值
、且
经
常有范
围查询
(
between, >,<
,
>=,< =
)和
order by
、
group by
发
生的列,可考
虑
建立群集索引;
②
.
经
常同
时
存取多列,且
每
列都含有重
复值
可考
虑
建立
组
合索引;
③
.
组
合索引要尽量使
关键查询
形成索引覆盖,其前
导
列一定是使用最
频
繁的列。
二、不充份的
连
接条件:
例:表
card
有
7896
行,在
card_no
上有一个非聚集索引,表
account
有
191122
行,在
account_no
上有一个非聚集索引,
试
看在不同的表
连
接条件下,两个
SQL
的
执
行情况:
select sum(a.amount) from account a,card b where a.card_no = b.card_no
(
20
秒)
select sum(a.amount) from account a,card b where a.card_no = b.card_no and a.account_no=b.account_no
(
< 1
秒)
----
分析:
----
在第一个
连
接条件下,最佳
查询
方案是将
account
作外
层
表,
card
作内
层
表,利用
card
上的索引,其
I/O
次数可由以下公式估算
为
:
外
层
表
account
上的
22541
页
+
(外
层
表
account
的
191122
行
*
内
层
表
card
上
对应
外
层
表第一行所要
查
找的
3
页
)
=595907
次
I/O
在第二个
连
接条件下,最佳
查询
方案是将
card
作外
层
表,
account
作内
层
表,利用
account
上的索引,其
I/O
次数可由以下公式估算
为
:外
层
表
card
上的
1944
页
+
(外
层
表
card
的
7896
行
*
内
层
表
account
上
对应
外
层
表
每
一行所要
查
找的
4
页
)
= 33528
次
I/O
可
见
,只有充份的
连
接条件,真正的最佳方案才会被
执
行。
总结
:
1.
多表操作在被
实际执
行前,
查询优
化器会根据
连
接条件,列出几
组
可能的
连
接方案并从中找出系
统开销
最小的最佳方案。
连
接条件要充份考
虑带
有索引的表、行数多的表;内外表的
选择
可由公式:外
层
表中的匹配行数
*
内
层
表中
每
一次
查
找的次数确定,乘
积
最小
为
最佳方案。
2.
查
看
执
行方案的方法
--
用
set showplan
on
,打
开
showplan
选项
,就可以看到
连
接
顺
序、使用何
种
索引的信息;想看更
详细
的信息,需用
sa
角色
执
行
dbcc(3604,310,302)
。
三、不可
优
化的
where
子句
1.
例:下列
SQL
条件
语
句中的列都建有恰当的索引,但
执
行速度却非常慢:
select * from record where
substring(card_no,1,4)='5378'(13
秒
)
select * from record where
amount/30< 1000
(
11
秒)
select * from record where
convert(char(10),date,112)='19991201'
(
10
秒)
分析:
where
子句中
对
列的任何操作
结
果都是在
SQL
运行
时
逐列
计
算得到的,因此它不得不
进
行表搜索,而没有使用
该
列上面的索引;
如果
这
些
结
果在
查询编译时
就能得到,那
么
就可以被
SQL
优
化器
优
化,使用索引,避免表搜索,因此将
SQL
重写成下面
这样
:
select * from record where card_no like'5378%'
(
< 1
秒)
select * from record where amount< 1000*30
(
< 1
秒)
select * from record where date= '1999/12/01'
(
< 1
秒)
你会
发现
SQL
明
显
快起来!
2.
例:表
stuff
有
200000
行,
id_no
上有非群集索引,
请
看下面
这
个
SQL
:
select count(*) from stuff where id_no in('0','1')
(
23
秒)
分析:
---- where
条件中的
'in'
在
逻辑
上相当于
'or'
,所以
语
法分析器会将
in ('0','1')
转
化
为
id_no ='0' or id_no='1'
来
执
行。
我
们
期望它会根据
每
个
or
子句分
别查
找,再将
结
果相加,
这样
可以利用
id_no
上的索引;
但
实际
上(根据
showplan
)
,
它却采用了
"OR
策略
"
,即先取出
满
足
每
个
or
子句的行,存入
临时
数据
库
的工作表中,再建立唯一索引以去掉重
复
行,最后从
这
个
临时
表中
计
算
结
果。因此,
实际过
程没有利用
id_no
上索引,并且完成
时间还
要受
tempdb
数据
库
性能的影响。
实
践
证
明,表的行数越多,工作表的性能就越差,当
stuff
有
620000
行
时
,
执
行
时间
竟达到
220
秒!
还
不如将
or
子句分
开
:
select count(*) from stuff where id_no='0'select count(*) from stuff where id_no='1'
得到两个
结
果,再作一次加法合算。因
为每
句都使用了索引,
执
行
时间
只有
3
秒,在
620000
行下,
时间
也只有
4
秒。
或者,用更好的方法,写一个
简单
的存
储过
程:
create
proc count_stuff asdeclare @a intdeclare @b intdeclare @c intdeclare @d
char(10)beginselect @a=count(*) from stuff where id_no='0'select
@b=count(*) from stuff where id_no='1'endselect @c=@a+@bselect
@d=convert(char(10),@c)print @d
直接算出
结
果,
执
行
时间
同上面一
样
快!
----
总结
:
----
可
见
,所
谓优
化即
where
子句利用了索引,不可
优
化即
发
生了表
扫
描或
额
外
开销
。
1.
任何
对
列的操作都将
导
致表
扫
描,它包括数据
库
函数、
计
算表达式等等,
查询时
要尽可能将操作移至等号右
边
。
2.in
、
or
子句常会使用工作表,使索引失效;如果不
产
生大量重
复值
,可以考
虑
把子句拆
开
;拆
开
的子句中
应该
包含索引。
3.
要善于使用存
储过
程,它使
SQL
变
得更加灵活和高效。
从以上
这
些例子可以看出,
SQL
优
化的
实质
就是在
结
果正确的前提下,用
优
化器可以
识别
的
语
句,充份利用索引,减少表
扫
描的
I/O
次数,尽量避免表搜索的
发
生。其
实
SQL
的性能
优
化是一个
复杂
的
过
程,上述
这
些只是在
应
用
层
次的一
种
体
现
,深入研究
还
会
涉
及数据
库层
的
资
源配置、网
络层
的流量控制以及操作系
统层
的
总
体
设计
。
分享到:
相关推荐
"SQL运行得更快"这个主题涵盖了多种优化策略和技术,旨在帮助用户更好地理解和应用这些方法。以下是对PDF文件"SQL运行得更快"中可能涉及的关键知识点的详细阐述: 1. **查询优化器**:SQL查询优化器是数据库管理...
本文将从三个方面深入探讨如何优化SQL,让其运行更快:不恰当的索引设计、不充分的连接条件以及不可优化的WHERE子句。 首先,不合理的索引设计是导致SQL运行慢的常见原因。例如,当在一个高重复值的列上建立非聚集...
SQL 优化是数据库管理员和开发者经常遇到的问题,如何让 SQL 运行得更快是数据库性能优化的关键。通过对索引设计和连接条件的优化,可以大幅度提高 SQL 的执行速度。 一、索引设计的重要性 索引是数据库中一个非常...
总的来说,SQL优化是一个涉及多个层面的综合过程,包括但不限于索引设计、查询结构优化、连接条件的设置等。优化时应考虑实际的查询需求和数据分布,同时理解数据库的内部工作原理,如查询优化器如何选择执行计划,...
《如何让你的SQL运行得更快——实例分析》 在当今的互联网时代,数据库管理与查询效率至关重要,尤其是在处理大量数据的在线事务处理(OLTP)和决策支持系统(DSS)中。SQL(结构化查询语言)是数据库操作的基础,...
本文将深入探讨如何通过合理的设计和调整索引来改善SQL的执行效率,从而让SQL运行得更快。 首先,我们需要理解索引的工作原理。索引是数据库中用于快速查找数据的数据结构,类似于书籍的目录。在非群集索引中,数据...
在SQL Server中,让SQL运行得更快是数据库管理员和开发人员的重要任务,因为这直接影响到系统的性能和用户体验。本文将探讨三个关键优化方面:索引设计、连接条件和WHERE子句优化。 首先,我们来看不合理的索引设计...
### 案例学习:如何让你的SQL运行得更快 #### 一、不合理的索引设计 在数据库操作中,索引的设计对于SQL查询效率的影响至关重要。合理的索引设计能够显著提升查询速度,而不合理的索引则可能导致性能瓶颈。本文...
在数据库管理中,SQL优化是提升系统性能的关键环节,特别是在Oracle数据库环境下。Oracle性能管理是一个系统性的、逐步的过程,它涉及到主动和被动两种管理模式。主动性能管理强调在系统设计和开发阶段就考虑高性能...
7. **硬件升级**:提升服务器硬件配置,如增加CPU核心数、提高内存容量和使用更快的硬盘,可以显著改善SQL Server 2005的运行性能。 8. **监控与调优工具**:使用SQL Server Profiler跟踪查询性能,找出慢查询并...
以下是一些关于如何提升SQL运行速度的关键知识点: 1. **索引设计**: - **非群集索引**:非群集索引在物理存储上并不按照索引排序,数据分散在数据页上。对于范围查询,可能需要全表扫描来获取所有符合条件的行,...
【高性能SQL优化】是数据库管理领域中的重要主题,旨在提高SQL语句的执行效率,以提升整个系统的性能。Oracle数据库是这一领域的佼佼者,它提供了丰富的工具和技术用于SQL优化。 Oracle性能管理分为两种类型:主动...
通过监控这些方面,可以帮助您更好地了解 SQL Server 的运行状况,并且能够快速诊断和解决问题。 监控 SQL Server 的运行状况是数据库管理员的重要任务之一。通过使用动态管理视图和动态管理函数,数据库管理员可以...
- 虽然这不是优化策略,但增加RAM、更快的磁盘I/O或者使用SSD都能提高SQL查询的执行速度。 10. **数据库设计**: - 最后,评估数据库的设计,看是否有冗余数据,或者是否可以通过范式化减少数据冗余和JOIN操作。 ...
除了上述方法,还可以通过重构SQL语句、使用索引、避免全表扫描、减少子查询、优化联接顺序等方式进行SQL优化。例如,创建合适的索引可以加速查询,但过多的索引可能会增加插入、更新和删除操作的开销。因此,索引的...
### SQL优化要点详解 #### 一、SQL性能问题的原因及解决方法 SQL性能问题是数据库管理中常见的挑战之一,它直接影响到系统的响应时间和整体性能。理解SQL性能问题的原因及其解决方法对于提升系统的运行效率至关...
更优更快 人工智能自动SQL优化----------http://www.sina.com.cn 2001/12/12 17:48 中国电脑教育报文/SQL爱好者 所谓SQL,就是指Structured Query Language(结构化查询语言),它是目前使用最广泛的数据库语言,用来...
4. **性能优化建议**:当编写可能影响性能的查询时,SQLPrompt会给出优化建议,比如使用更高效的索引或者重写查询结构,有助于提升SQL Server的执行效率。 5. **代码片段管理**:内置了大量的代码片段,可以自定义...