您好, 访客   登录/注册

基于关系数据库的SQL查询语句执行过程效率分析与对策

来源:用户上传      作者: 彭易波

  [摘要]基于关系数据库的标准查询语言SQL在数据库系统中被广泛使用,在使用SQL查询和检索数据时往往只注重正确性,忽略其效率性。从SQL查询语句执行过程入手,先解析执行过程,然后根据执行过程提出优化策略,使其在正确前提下,提高其运行效率。
  [关键词]关系数据库SQL查询对策
  中图分类号:TP3文献标识码:A文章编号:1671-7597(2009)1210080-01
  在各类大型应用软件的数据库中,都存在大量的数据信息和记录,经常要对它们进行各种数据操作。SQL(Structrued Query Language)作为结构化查询语言,是大型计算机操作关系数据库的标准查询语言,同时也广泛地应用到小型计算机的数据库管理系统中。它是一种高度非过程化的语言,即只要用户按其语法规则写出符合操作要求的语句,而并不需要告诉系统应如何执行SQL语句,就可得到所要求的结果。随着数据库技术的广泛应用,在数据库程序的开发过程中,大量的工作是要进行数据查询和检索处理。本文从SQL查询语句执行的过程入手,对其执行效率进行分析,并给出参考性建议和优化策略。
  
  一、SQL语句执行过程解析
  
  在平时书写SQL查询语句时,虽然每个人的写法不尽相同,而且有时个别子句顺序并不影响操作结果,但是在各种数据库管理系统中,标准的SQL的解析顺序为:
  1.FROM子句,组装来自不同数据源的数据;
  2.WHERE子句,基于指定的条件对记录进行筛选;
  3.GROUP BY子句,将数据划分为多个分组;
  4.使用聚合函数进行计算;
  5.使用HAVING子句筛选分组;
  6.计算所有的表达式;
  7.使用ORDER BY对结果集进行排序。
  通过以上SQL语句的解析过程,我们可以对SQL查询语句进行优化处理。SQL查询语句的核心结构是SELECT…FROM…WHERE,了解了这个基本结构,我们可以从以下几个方面对其进行优化处理。
  
  二、效率分析及优化对策
  
  (一)从From子句入手
  From子句后面接单表或者多表,通常情况下接受来自不同数据源的多表。如果是单表,一般情况下对表进行快速全表扫描。如果是多表的情况,查询设计优化器将采取自右向左的顺序依次读取数据表。如以下语句:“From table1,table2,table3”,优化器将优先读取table3表,然后是table2表,最后是table1表。在进行From子句的多表连接时,就需要结合条件子句WHERE进行分析,需要遵循下面的规则:1. 当WHERE后面接的条件能够一次性过滤某个表的大量记录时,应优先处理该表。2. 如果WHERE后面接的条件不能过滤掉大量记录时应该优先考虑处理记录数最少或者索引关键值最少的表。
  (二)从条件子句WHERE入手
  WHERE子句后面通常接过滤条件,对表的记录进行筛选,筛选出符合条件的记录。如果SELECT查询语句没有WHERE子句,则无须对表记录进行过滤。若后面接单个表,则通常顺序扫描全表。若后接多表或者大量记录表时,则可以考虑用索引来减少查询的时间。所以在查询前可对各个表建立比较的索引。对WHERE子句中出现的条件,可以依据以下原则首先来驱动查询。
  (1)建立索引字段的列比没有建立索引的要快;(2)主索引要比普通索引快;(3)单索引要比符合索引快;(4)有条件约束要比没有条件约束要快。
  此外,WHERE子句通常采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。根据以上原则,我们可以判断出以下四个语句中哪个选项语句效率最高。
  Select * Frommobilewhere (mobileno='13775637677') andbegINtime>
  {^2009-1-308:20:11} andbegintime<{^2009-9-308:20:11}
  B) SELECT*Frommobilewhere(mobileno='13775637677' )andbegINtime<
  {^2009-1-30 8:20:11} andbegintime>{^2009-1-30 8:20:11}
  C) SELECT*Frommobilewherebegintime<{^2009-9-30 8:20:11}andbegINtime>
  {^2009-1-308:20:11}and(mobileno='13775637677' )
  很显然,综合以上原则C选项效率最高。
  (三)从GROUP BY和HAVING子句入手
  在SELECT语句中,GROUP BY语句的作用是对记录进行分组(划分成较小的组),使用聚合函数返回每一个组的汇总信息,而HAVING子句限制返回的结果集。在一个SQL语句中可以有WHERE子句和HAVING子句。HAVING与WHERE子句类似,均用于设置限定条件。WHERE子句的作用是在对查询结果进行分组前,将不符合WHERE条件的记录过滤掉,而HAVING子句的作用是筛选满足条件的组,即在分组之后过滤数据,但它不能单独使用,只能配合GROUP By语句使用,该条件中经常包含聚组函数,使用HAVING条件显示特定的组,也可以使用多个分组标准进行分组。虽然HAVING子句可以起到过滤的作用,但是要尽量避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。如果能通过WHERE子句限制记录的数目,而且能尽早地把不满足条件的记录过滤掉,那就能减少这方面的开销。
  (四)从谓词等方面入手
  在SELECT语句中,由于实际需要,查询语句会经常出现谓词。常用的谓词有EXIST,NOT EXSIT,IN,NOT IN等,巧用谓词也会提高SQL语句的执行效率,可参考以下原则编写SQL语句。
  1.Where子句中尽量不要使用IS NULL或IS NOT NULL的语句,因为它们不会使用索引。
  2.WHERE子句尽量不要将通配符(%)放在搜寻词首出现,通配符(%)在搜寻词首出现不会使用索引。
  3.用EXISTS代替IN。在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用EXISTS(或NOT EXISTS)通常将提高查询的效率。
  4.用表连接代替EXISTS。通常来说,采用表连接的方式比EXISTS更有效率。
  5.用EXISTS代替DISTINCT。当提交一个包含一对多表信息(比如班级表和学生表)的查询时,避免在SELECT子句中使用DISTINCT。一般可以考虑用EXIST替换。
  
  6.WHERE子句尽量少使用NOT或是<>,应该成OR来实行,使用OR时应该把结果集小的条件放在前面。
  7.UNION改用UNION ALL,UNION要对合并的结果进行排序,UNION ALL不排序。
  8.ORDER BY子句中尽量不要使用非索引列。
  
  三、结语
  
  通过对SQL查询语句执行过程的分析,可以从以上几个方面对其进行优化改进,从而提高了数据库查询和检索的效率。当然,具体的查询语句还要根据具体需要,并结合具体的数据库系统而定。只有多总结多积累才能写出高质量高效率的查询语句,当然这只是提高数据检索的一个方面,在其他方面的设计也要进行优化,如对表建立必要的索引,减少表之间的连接,或尽量在索引属性列上建立连接等。总之,通过以上几个方面的综合优化,一定会使数据库查询与检索效率有很大的提高。
  参考文献:
  [1]王振辉、吴广茂,SQL查询语句优化研究[J].计算机应用,2005,25(12).
  [2]徐凤梅,关系数据库中SQL查询语言的优化策略[J].广西轻工业,2009,126(5).
  [3]邓文艳,基于关系数据库的查询优化技术[J].太原科技,2007(12).
  [4]杨克昌,Visual FoxPro程序设计教程[M].长沙:湖南科学技术出版社,2004.
  [5]李莹、代勤,关系代数运算与SQL查询的对应关系[J].内蒙古农业大学学报(自然科学版),2003,24(3).
  
  
  作者简介:
  彭易波,助教,主要研究方向:数据库,无线传感器,计算机应用。


转载注明来源:https://www.xzbu.com/8/view-1067033.htm