论文导读:影响SQLServer性能的因素很多。合理的使用索引能在很大程度上加速数据的读取。使用合理的索引是优化查询性能的有效手段之一。
关键词:SQLServer,数据库模型,优化查询,索引
正文:
随着计算机技术的飞速发展,作为企业级数据库服务器SQL Server在性能、可扩展性等方面对于数据库系统提出了更为严格的要求。依据SQL Server的响应时间、吞吐量和可扩展性等方面来判定其性能。影响SQLServer性能的因素很多,大致分为:应用程序的体系结构的设计、数据库模型和物理设计、事务与隔离级别的选择、Transact—SQL语句设计、硬件资源配置及SQL Server配置参数设定等几个方面。我们就数据库模型设计、Transact—SQL语句设计和常用优化技术三方面来讨论。
一、合理设计数据库模型
设计不良的数据库模型会导致数据查询、修改等操作效率的降低。为了避免这类问题,可以从以下几点考虑。
1.数据库模型的范式
范式是对关系规范化的约束要求,规范化理论将关系应该满足的规范要求分成几级,主要包括第一范式(1NF)、第二范式(2 NF)、第三范式(3NF)、鲍依斯-科得范式(BC NF)、第四范式(4 NF)和第五范式(5 NF)等。范式越高,越能够有效消除数据冗余,理顺数据隶属关系,保持数据库的完整性,提高数据库的稳定性和扩展性。但是越高的范式需要更多的表,在检索同样信息的查询中需要的连接操作也会更多,造成需要更多的系统机缘来优化执行,最终导致数据库系统中查询的性能的降低。以下面两个模型为例,在模型1使用一张表代表职工;模型2中将职工表的信息细化成为两张表——职工表和部门表。
模型1:
Employee(
Emp_NOchar(8) not null,
Emp_Name char(8),
Emp_addrs char(20),
Emp_birth datetime,
Emp_wyer datetime,
Depart_Name char(10),
Depart_phonechar(20)
)
模型2:
Employee(
Emp_NOchar(8) not null,
Emp_Name char(8),
Emp_addrs char(20),
Emp_birth datetime,
Emp_wyer datetime
)
Department(
Depart_No Char(8),
Depart_Name char(10),
Depart_phonechar(20)
)
若查询职员和部门信息,对于模型1,只需进行简单扫描即可,而模型2 则需要进行职员表和部门表的连接操作;然而模型1相对于模型2存在数据冗余,若进行部门电话信息的更新操作,模型1必须更新多行记录及更多的加锁和日志记录,而模型2则只需更新部门表中的移行记录即可。由此看出,选择合适的数据库模型,影响着应用程序的性能。科技论文,优化查询。
2.使用合理的索引
合理的使用索引能在很大程度上加速数据的读取,提高查询速度,使应用程序获得更好的性能,相反,不必要的索引会增加数据修改操作不必要的开支,浪费数据库中的空间。因此,使用合理的索引是优化查询性能的有效手段之一。
(1) 聚集索引的使用
聚集索引的建立使得数据的物理存储与索引数据的顺序一致,因此对于提高查询效率十分有效。诸如Between、> 、>=等一类需要排序数据来匹配聚集码的范围值查询是非常有效的。同样,对于访问连续列或者含有重复值很少的大量数据列,亦或者经常使用连接、排序(ORDER BY)或分组(GROUP BY)统计等查询访问的情况也很适用。SQL Server 在声明PRIMARY KEY(主键)约束时,为主键同时创建了唯一聚集索引,但在某种情况下,反而会造成查询速度的减慢。以模型2中的数据表employee为例,查询工龄超过10年的职工信息,使用下列代码段查看查询花费时间:
DECLARE@t datetime
Set@t=getdate()
Select *from employee where emp_wyer > dateadd(yy,-10,getdate())
Select‘该查询执行所花费的时间(毫秒)为’=datediff(ms,@t,getdate())
通过设置分别在主键(emp_no)上建立聚集索引,在emp_wyer(参加工作时间)建立非聚集索引与在主键(emp_no)上建立非聚集索引,在emp_wyer上建立聚集索引两种情况的耗时对比,发现并不是在主键上建立聚集索引都是最好的选择。因此,有时在主键约束上设置nonclustered对于查询速度的提高会更有效。
(2) 非聚集索引的使用
查询优化器对非聚集索引的支持相对较聚集索引少一些。当非聚集索引具有高选择性,也就是说消除了大量的行以后才对查询有用。一般常常基于频繁使用的查询的条件子句中的属性列建立索引,但该索引的有效性依赖于其选择性程度的高低。若根据表中符合条件的行数与表中总行数之比来描述索引的选择性的话,其比值越小,索引的选择性越高,原因在于,索引可以将表中大部分的行排除。以查询名叫“刘倩”的职工信息为例,此时若存在基于emp_name的索引就非常的有效,可能排除99.9%的行,但若按照性别来查找职工信息,则非聚集索引仅能排除50%的行,几乎没有什么作用。因此,一般非聚集索引常常使用在重复值很少或列的更新频率较高亦或者需要频繁修改索引列的情况。
(3) 覆盖索引的使用
覆盖索引是包含了所有被引用属性列的索引,该索引同样能够提高数据的访问速度。数据表中的聚集索引包含了表中所有的属性列。在SQL Server2005中,创建非聚集索引时使用INCLUDE子句添加其他非关键列,可实现覆盖更多的列,从而提高SQL Server在页中存储行的数量,节省磁盘空间提高查询的效率。以下面模式为例,描述索引关键列与已覆盖列的关系:
CREATETABLE table1 (t1 char(3),t2 char(3), t3 char(3), t4 char(3) ,t5 char(3))
CREATEINDEX IX_t1t2 ON table1(t1,t2)
CREATEINDEX IX_t1 ON table1(t1) INCLUDE(t2)
其中,非聚集索引IX_t1t2的关键列为t1和t2,覆盖的列为t1和t2;而IX_t1的关键列为t1,覆盖的列为t1和t2。对于查询SELECT t1,t2 from table1where t1 like ‘1_[0-5]’,可以说索引IX_t1“覆盖”了这一条查询,也就是在t2属性列的值的读取时,SQL Server查询优化器可以简单对非聚集索引B-tree的叶子页访问实现。因此,在某些情况下,适当的使用索引覆盖能够提高查询的性能,实现查询的优化。
(4)根据需求创建和删除索引
多表查询中经常会使用到连接,嵌套循环连接是最简单和基础的连接方式,即将两个表中的行与行之间进行比较,查找满足连接条件的行。在SQLServer中对于嵌套循环连接提高性能的重要技术之一就是,关联参数与连接内部基于关联参数的索引查询。由于在表中创建FROEIGN KEY约束时,不会自动基于所使用的属性列创建索引,因此需要根据实际情况在关联属性列上创建索引。
使用的索引的一个很重要的目的就是提高查询速度,但同时也占用了一定的磁盘空间。已经创建的、不经常使用的索引不仅不能够提高查询速度,反而会消耗磁盘空间,减缓数据更新的速度,影响查询性能。因此根据SHOWPLAN选项产生的计划分析确定极少被使用的索引,进行删除。
二、重写查询
不同书写方式的实现同一查询操作的查询语句,同样影响着查询速度。科技论文,优化查询。SQL Server的查找效率在很大程度上取决于是否选择了合适的谓词。如果一个查找谓词可以过滤掉表中的大部分不符合要求的内容,这样的查询效率会更高一些。
1.避免使用复杂的谓词
复杂的谓词(如列中的函数、带有引导通配符的Like等)会导致SQL Server不使用索引查找。例如,存在基于EMP_Name的单列索引,对于类似EMP_Name like ‘%林’、len(EMP_Name)=1的谓词,不能使用该索引进行查找。如果可以尽可能的使用“=”,减少使用“like “。
2.避免使用复合索引中的非首列作为Where子句的第一个条件
如果表中存在复合索引,该复合索引关键字的顺序决定了索引的排序方式,也就影响着SQL Server使用索引的查找。因此,在书写where子句时,尽可能的将第一列上的谓词放在所有条件之前(避免使用复杂谓词),这样能够使SQLServer使用该索引进行查找。
3.合理使用子查询
子查询分为相关子查询和不相关子查询两种类型。不相关子查询不依赖于外部查询,其查询的独立于外部查询;而相关子查询依赖于外部查询,当外部查询中的列值发生改变时,子查询需要重新查询,引起磁盘IO操作增加,降低了查询效率。通过对SQL Server的查询优化器对不同子查询所选择的连接顺序和类型分析来看,如果存在语义、功能上相等的不相关子查询和相关子查询情况时,建议使用不相关子查询。如果不可避免的使用到相关子查询,那么尽可能的将子查询的范围尽可能缩小。科技论文,优化查询。对于不相关的梯状子查询来说,建议重写为多个子查询,这样可以进一步提高查询效率。
4.避免使用不可求值的查询条件
如果数据库引擎能够使用索引搜索加速查询的执行,那么该查询中的条件就是可求值的。对于带有不可求值查询条件的查询语句,会导致扫描全表,降低查询效率。科技论文,优化查询。因此在查询中的where子句中尽可能的避免使用不可求值的表达式,即避免将列引用在表达式或函数中,以及使用否定操作符(比如,NOT、NOT IN、!=和NOT LIKE,以及通配符引导的字符串)。常见的不可求值的表达式如下:abs(price)>8,emp_name like ‘%清%’。同时尽可能的避免使用OR连接多个条件,原因在于单个的索引扫描不能用来限制所有的条件。以“emp_name =’李明’and Emp_wyer >15”为例,此时第二个条件的查询会基于第一条件使用索引查找后的集合中进行查询(假设存在基于列emp_name的索引)。对于“emp_name=’李明’OR Emp_wyer >15”查询条件,在第二个条件将会重新扫描全表或重新使用索引查找,因此会降低查询速度。对于这样的情况,可以使用union重写查询。
三、常用优化技巧
1.合理使用临时表
与永久表相比,临时表具有需要时创建,不需要时删除的特点,它可在数据处理的过程中减少很多中间表的使用。比如,根据需要自动创建临时表,代替操作所需要的中间表,使用后在自动删除,既可以节省磁盘的存储量,又可以减少用户的工作量,提高数据库性能。利用临时表组织数据也可以有效的提高查询效率,比如,通过在临时表中创建更优化的索引取代基本表中的不恰当地索引,提高索引的使用效率;或者当需要多次访问某一个表或者视图时,使用临时表进行组织经常访问的数据,此时临时表的记录数一般少于基本表的记录数,从而减少了查询的工作量。科技论文,优化查询。
2.善于使用存储过程
存储过程是一组编译在单个执行计划中的Transact-SQL语句,是SQL语句和控制流语句的与编译的集合,当存储过程第一次执行后,SQL Server为其产生的查询计划被保留在内存中,再次使用时直接执行查询计划,不需要再次编译、优化,从而改善了系统的性能。存储过程通过本地存储、代码预编译及缓存技术能够实现高效的数据操作,合理的使用存储过程不仅方便程序员进行程序设计,同时可以极大的提高SQL语言的效率;若将其使用在服务器上,将有助于减少向客户端传输的数据量,提高传输和处理数据的效率。科技论文,优化查询。
四、结束语
优化查询可以极大的改善数据库(尤其是大型数据库)的性能。在优化过程中,需要根据具体的情况具体分析选择最佳的优化方案。在合理的设计数据库模型的基础上,灵活的使用重写查询方法,提高SQL查询语句的执行效率,善于使用临时表和存储过程,减少对内存的需求及编译优化的时间,从而达到提高查询速度,优化数据库性能的目的。
参考文献:
[1]规范化-数据库设计原则:[EB/OL]
http://www-128.ibm.com/developerworks/cn/db2/library/techarticles/dm-0605jiangt/index.html;
|