`
floger
  • 浏览: 213264 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

(转)SQL 查询效率

阅读更多

 

很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解。比如: 

select * from table1 where name='zhangsan' and tID > 10000  
 

和执行: 

select * from table1 where tID > 10000 and name='zhangsan'
    

一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那么后一句仅仅从表的10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name='zhangsan'的,而后再根据限制条件条件tID>10000来提出查询结果。 

事实上,这样的担心是不必要的。SQL SERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。 

虽然查询优化器可以根据where子句自动的进行查询优化,但大家仍然有必要了解一下“查询优化器”的工作原理,如非这样,有时查询优化器就会不按照您的本意进行快速查询。 

在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用索引快速获得所需数据。 

SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的AND连接。形式如下: 

列名 操作符 <常数 或 变量> 

或 

<常数 或 变量> 操作符列名 

列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如: 

Name=’张三’ 

价格>5000 

5000<价格 

Name=’张三’ and 价格>5000 

如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。 

介绍完SARG后,我们来总结一下使用SARG以及在实践中遇到的和某些资料上结论不同的经验: 

1、Like语句是否属于SARG取决于所使用的通配符的类型

如:name like ‘张%’ ,这就属于SARG 

而:name like ‘%张’ ,就不属于SARG。 

原因是通配符%在字符串的开通使得索引无法使用。 

2、or 会引起全表扫描

Name=’张三’ and 价格>5000 符号SARG,而:Name=’张三’ or 价格>5000 则不符合SARG。使用or会引起全表扫描。 

3、非操作符、函数引起的不满足SARG形式的语句

不满足SARG形式的语句最典型的情况就是包括非操作符的语句,如:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE等,另外还有函数。下面就是几个不满足SARG形式的例子: 

ABS(价格)<5000 

Name like ‘%三’ 

有些表达式,如: 

WHERE 价格*2>5000 

SQL SERVER也会认为是SARG,SQL SERVER会将此式转化为: 

WHERE 价格>2500/2 

但我们不推荐这样使用,因为有时SQL SERVER不能保证这种转化与原始表达式是完全等价的。 

4、IN 的作用相当与OR

语句: 

Select * from table1 where tid in (2,3)
    

和 

Select * from table1 where tid=2 or tid=3
    

是一样的,都会引起全表扫描,如果tid上有索引,其索引也会失效。 

5、尽量少用NOT

6、exists 和 in 的执行效率是一样的

很多资料上都显示说,exists要比in的执行效率要高,同时应尽可能的用not exists来代替not in。但事实上,我试验了一下,发现二者无论是前面带不带not,二者之间的执行效率都是一样的。因为涉及子查询,我们试验这次用SQL SERVER自带的pubs数据库。运行前我们可以把SQL SERVER的statistics I/O状态打开。 

(1)select title,price from titles where title_id in (select title_id from sales where qty>30) 

该句的执行结果为: 

表 'sales'。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。 

表 'titles'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。 

(2)
select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty>30)  

 

第二句的执行结果为: 

表 'sales'。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。 

表 'titles'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。 

我们从此可以看到用exists和用in的执行效率是一样的。 

7、用函数charindex()和前面加通配符%的LIKE执行效率一样

前面,我们谈到,如果在LIKE前面加上通配符%,那么将会引起全表扫描,所以其执行效率是低下的。但有的资料介绍说,用函数charindex()来代替LIKE速度会有大的提升,经我试验,发现这种说明也是错误的: 

select gid,title,fariqi,reader from tgongwen where charindex('刑侦支队',reader)>0 and fariqi>'2004-5-5'
   

用时:7秒,另外:扫描计数 4,逻辑读 7155 次,物理读 0 次,预读 0 次。 

select gid,title,fariqi,reader from tgongwen where reader like '%' + '刑侦支队' + '%' and fariqi>'2004-5-5'
    

用时:7秒,另外:扫描计数 4,逻辑读 7155 次,物理读 0 次,预读 0 次。 

8、union并不绝对比or的执行效率高

我们前面已经谈到了在where子句中使用or会引起全表扫描,一般的,我所见过的资料都是推荐这里用union来代替or。事实证明,这种说法对于大部分都是适用的。 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
where fariqi='2004-9-16' or gid>9990000
   

用时:68秒。扫描计数 1,逻辑读 404008 次,物理读 283 次,预读 392163 次。 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
where fariqi='2004-9-16'  

union  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
where gid>9990000  
 

用时:9秒。扫描计数 8,逻辑读 67489 次,物理读 216 次,预读 7499 次。 

看来,用union在通常情况下比用or的效率要高的多。 

但经过试验,笔者发现如果or两边的查询列是一样的话,那么用union则反倒和用or的执行速度差很多,虽然这里union扫描的是索引,而or扫描的是全表。 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen
where fariqi='2004-9-16' or fariqi='2004-2-5' 
 

用时:6423毫秒。扫描计数 2,逻辑读 14726 次,物理读 1 次,预读 7176 次。 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
where fariqi='2004-9-16'  

union  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
where fariqi='2004-2-5'  
 

用时:11640毫秒。扫描计数 8,逻辑读 14806 次,物理读 108 次,预读 1144 次。 

9、字段提取要按照“需多少、提多少”的原则,避免“select *”

我们来做一个试验: 

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc  

用时:4673毫秒  

select top 10000 gid,fariqi,title from tgongwen order by gid desc  

用时:1376毫秒  

select top 10000 gid,fariqi from tgongwen order by gid desc  

用时:80毫秒  
 

由此看来,我们每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。 

10、count(*)不比count(字段)慢

某些资料上说:用*会统计所有列,显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看: 

select count(*) from Tgongwen  

用时:1500毫秒  

select count(gid) from Tgongwen  

用时:1483毫秒  

select count(fariqi) from Tgongwen  

用时:3140毫秒  

select count(title) from Tgongwen  

用时:52050毫秒  
 

从以上可以看出,如果用count(*)和用count(主键)的速度是相当的,而count(*)却比其他任何除主键以外的字段汇总速度要快,而且字段越长,汇总的速度就越慢。我想,如果用count(*), SQL SERVER可能会自动查找最小字段来汇总的。当然,如果您直接写count(主键)将会来的更直接些。 

11、order by按聚集索引列排序效率最高

我们来看:(gid是主键,fariqi是聚合索引列) 

select top 10000 gid,fariqi,reader,title from tgongwen  

用时:196 毫秒。 扫描计数 1,逻辑读 289 次,物理读 1 次,预读 1527 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc  

用时:4720毫秒。 扫描计数 1,逻辑读 41956 次,物理读 0 次,预读 1287 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc  

用时:4736毫秒。 扫描计数 1,逻辑读 55350 次,物理读 10 次,预读 775 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc  

用时:173毫秒。 扫描计数 1,逻辑读 290 次,物理读 0 次,预读 0 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc  

用时:156毫秒。 扫描计数 1,逻辑读 289 次,物理读 0 次,预读 0 次。  
 

从以上我们可以看出,不排序的速度以及逻辑读次数都是和“order by 聚集索引列” 的速度是相当的,但这些都比“order by 非聚集索引列”的查询速度是快得多的。 

同时,按照某个字段进行排序的时候,无论是正序还是倒序,速度是基本相当的。 

12、高效的TOP

事实上,在查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0操作。如: 

select top 10 * from (  

select top 10000 gid,fariqi,title from tgongwen  

where neibuyonghu='办公室'  

order by gid desc) as a  

order by gid asc  
 
这条语句,从理论上讲,整条语句的执行时间应该比子句的执行时间长,但事实相反。因为,子句执行后返回的是10000条记录,而整条语句仅返回10条语句,所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用,发现TOP确实很好用,效率也很高。但这个词在另外一个大型数据库ORACLE中却没有,这不能说不是一个遗憾,虽然在ORACLE中可以用其他方法(如:rownumber)来解决。在以后的关于“实现千万级数据的分页显示存储过程”的讨论中,我们就将用到TOP这个关键词。   

 

分享到:
评论

相关推荐

    sql查询效率

    ### SQL查询效率提升详解 #### 一、理解SQL查询优化的重要性 在当今数据驱动的世界里,高效地查询数据库成为了一项关键技能。SQL查询优化旨在减少处理查询所需的时间,从而提高系统的整体性能。优化不仅涉及编写更...

    sql查询优化(提高MySQL数据库查询效率的几个技巧)

    SQL 查询优化(提高 MySQL 数据库查询效率的几个技巧) 在 MySQL 数据库中,查询优化是一个非常重要的方面。在实际应用中,高效的查询可以提高整个系统的性能和响应速度。下面我们将介绍几个提高 MySQL 数据库查询...

    Oracle提高SQL查询效率(SQL优化).doc

    Oracle 提高 SQL 查询效率(SQL 优化) 本文将详细介绍 Oracle 中提高 SQL 查询效率的技巧和策略,包括选择最有效率的表名顺序、WHERE 子句中的连接顺序、SELECT 子句中避免使用‘*’、减少访问数据库的次数、使用 ...

    SQL Server查询性能分析与查询效率提高.pdf

    本文将详细探讨SQL Server查询性能分析及其效率提升的方法,以期帮助读者更好地理解和优化SQL Server中的数据查询。 首先,必须了解SQL Server中的查询优化机制。SQL Server使用名为“查询分析优化器”的组件来自动...

    影响sql语句查询效率的因素

    本文将深入探讨影响SQL语句查询效率的关键因素,特别关注查询优化与LIKE语句的使用,帮助数据库管理员和开发人员识别并解决查询性能瓶颈。 ### 影响SQL查询效率的因素 #### 1. **处理NULL值** 当SQL查询涉及对...

    提高sql查询效率的50种方法

    查询速度慢的原因很多,常见如下几种 可以通过如下方法来优化查询

    基于语义视图的SPARQL-SQL查询转换方法.pdf

    本体的使用能够清晰地描述领域概念模型和数据的语义信息,而将基于本体的语义查询转换为面向关系数据库的SQL查询,则是利用关系数据库的功能,提升查询效率和语义集成的关键步骤。 SPARQL查询是用于查询 RDF 数据...

    Oracle中SQL语句执行效率的查找与解决

    本文将深入探讨Oracle中SQL语句执行效率的查找与解决方法,特别关注于如何识别和优化那些导致性能瓶颈的查询。 ### Oracle SQL执行效率:查找与解决 #### 一、资源消耗分析 在Oracle中,SQL语句执行效率低下通常...

    Sql查询分析器

    "Sql查询分析器"是一款专为SQLServer设计的实用工具,它使得用户可以直接与数据库进行交互,执行SQL查询,从而高效地管理和分析数据。这款工具的便捷之处在于,它是一个可执行的exe文件,无需安装,只需解压缩后直接...

    运用数据库优化器提高SQL查询效率.pdf

    运用数据库优化器提高SQL查询效率 数据库优化器是数据库查询提供一个最优的执行策略,它可以大大提高SQL查询的效率。执行策略是执行查询所需的一系列步骤,数据库的反应速度经常体现在这个优化算法上。不同的查询...

    sql.rar_提高SQL查询效率的30种方法

    随着数据量的日益增长,优化SQL查询以提高效率变得至关重要。以下是一些提高SQL查询效率的30种方法,旨在帮助数据库管理员和开发人员提升查询性能。 1. **使用索引**:为经常用于搜索的列创建索引,可以显著加快...

    DBC数据转SQL数据 无限制工具

    总的来说,"DBC数据转SQL数据 无限制工具"是魔兽世界模拟器开发和数据分析领域的一个强大辅助工具,它简化了DBC和SQL之间的数据交互,提高了工作效率,同时它的无限制特性使得它成为了一个极具价值的资源。...

    提高Oracle中SQL的执行效率

    通过内部函数提高SQL效率 复杂SQL查询可能会牺牲执行效率。掌握并正确使用Oracle提供的内置函数可以帮助简化查询逻辑,提高查询性能。例如,使用`LISTAGG`函数来合并多个值为单个字符串,或者使用`CASE`表达式来...

    SQL查询效率:100w数据查询只需要1秒钟

    ### SQL查询效率提升技巧:如何实现100万数据秒级查询 在处理大量数据时,提高查询效率是至关重要的。本文将通过一系列步骤展示如何优化SQL查询性能,以达到即使是100万条记录也能在一秒钟内完成查询的目标。 ####...

    提高数据库SQL查询效率的方法.pdf

    文章讨论了提高数据库SQL查询效率的必要性和方法,首先强调了查询优化对数据库系统性能的重要性,并指出虽然有些程序员可能认为查询优化是数据库管理系统(DBMS)的任务,但实际上SQL语句的效率对数据库系统的性能起到...

    Oracle Sql语句转换成Mysql Sql语句

    在数据库管理领域,Oracle SQL和MySQL SQL是两种广泛使用的SQL方言,它们在语法和功能上存在一定的差异。当需要将一个基于Oracle SQL的应用程序迁移到MySQL环境时,就需要进行SQL语句的转换工作。本项目提供了一个...

    Microsoft SQL Server 2005技术内幕全套(三):T-SQL查询.part1

    因此,书中必定会讲解如何通过索引、查询优化器的工作原理以及查询执行计划来提升查询效率。最后,可能还会涵盖错误处理和异常处理机制,以确保程序的健壮性。 通过阅读《Microsoft SQL Server 2005技术内幕:T-SQL...

    sql server 查看执行效率不高的语句

    在SQL Server中,查询性能优化是一项关键任务,尤其是在处理大量数据和复杂业务逻辑时。当数据库中的查询执行效率不高时,不仅会影响应用的响应速度,还可能导致资源浪费和系统瓶颈。因此,掌握如何查看和分析执行...

    sql执行效率提高

    以下是一些针对提高 SQL 执行效率的重要知识点: 1. **选择最有效的表名顺序**:在 FROM 子句中,Oracle 从右到左处理表,所以应该先处理记录数最少的表,以减少扫描的数据量。对于多表联接,基础表(被其他表引用...

    Sql效率查询

    ### SQL效率查询知识点 在SQL性能优化领域,查询效率至关重要,尤其当数据库承载大量业务时,高效率的SQL查询能够显著提升系统响应速度并降低服务器负载。本文将围绕标题“SQL效率查询”及其描述“直接运行函数,...

Global site tag (gtag.js) - Google Analytics