原文地址:http://www.sqlpassion.at/archive/2014/04/08/improving-query-performance-by-using-correct-search-arguments/

Improving Query Performance by using correct Search Arguments

April 8, 2014 · Klaus Aschenbrenner ·

通过使用正确的search arguments来提高数据库的性能

今天的博客,我想谈谈在SQL Server上关于indexing的一个特定的性能问题

问题

看看下面的简单的query语句,可能你已经在你看到过几百次了

-- Results in an Index Scan
SELECT * FROM Sales.SalesOrderHeader
WHERE YEAR(OrderDate) = 2005 AND MONTH(OrderDate) = 7
GO

上门的代码查询一个销售信息,需要一个特定的月份和年份的,这不是很复杂。但是不幸的的事,这个qeury的效率不行,即使OrderDate这一列已经做了Non-Clustered Index。可以看看下面的qeury执行图,你能看到Query Optimizer已经选择了定义在列OrderDate下的Non-Clustered Index,但是SQL Server却做了Index的一个完整扫描,而不是期待中的Seek operation。

这实际上不是SQL Server的限制,而是relational database都是这样的。只要你对一个做了index的列(Search Argument)加了函数操作,数据库引擎就必须再次扫描这个index,而不是去直接执行seek operation

解决方案

为了解决上门的问题,必须要避免在列上门直接应该函数,比如上面的问题可以用下面的代码来代替

-- Results in an Index Seek
SELECT * FROM Sales.SalesOrderHeader
WHERE OrderDate >= '20050701' AND OrderDate < '20050801'
GO

我们重写的这个query语句,能达到同样的效果,不用函数MONTH了。从此query的执行图来看,SQL Server执行了seek operation,在查询的范围内进行的scan。所以,如果你要在where查询中用到函数,用到表达式的右侧,来避免性能问题。比如下面的例子。

-- Results in an Index Scan
SELECT * FROM Sales.SalesOrderHeader
WHERE CAST(CreditCardID AS CHAR(4)) = '1347'
GO

这个query会使SQL Server扫描了整个Non-Clustered Index。所以当表变得更大的时候,这个扩展性等各方面就很差了。如果把函数放在表达式的右侧,SQL Server就能执行seek operation了

-- Results in an Index Seek
SELECT * FROM Sales.SalesOrderHeader
WHERE CreditCardID = CAST('1347' AS INT)
GO

总结

通过今天的blog,我想你们已经认识到了不要在做过indexed的列上直接应用函数,不然SQL Server会扫描你整个index,而不是做seek operation。当你的表变得越来越大的时,你会崩溃的。


译后记

这也是我在看微软SQL Server认证考试Exam70-461的TrainingKit的时候,它书里面反复强调的。简单来讲就是保证不要直接用函数作用在做过index的列上,要用函数的话,变通到表达式的右侧来。至于为什么会影响性能。因为我对index还不熟悉,我理解的不是很清晰。

我大概猜想如下,先记下,欢迎讨论。

对某一个列做index,是不是类似对这一列的数据做一个hash映射,当在查找这一列的数据的时候,直接可以做O(1)的操作(是不是就是它讲的seek operation)。如果对这一列使用了函数,SQL Server的机制就是不会重新做一个作用了函数后的列的hash,它就简单的一个一个的比较了。是O(N)的操作了。

  

 

  

[翻译]通过使用正确的search arguments来提高SQL Server数据库的性能的更多相关文章

  1. SQL Server数据库自增字段正确的插入值的描述

    我们今天主要向大家讲述的是SQL Server数据库之向SQL Server自增字段正确的插入值的实际操作步骤,在一般的情况下,我们不能向 SQL Server 数据库自增字段中插入值,如果非要这么干 ...

  2. JeeSite如何正确连接SQL SERVER 数据库

    JeeSite如何正确连接SQL SERVER 数据库 jeesite介绍 感谢jeesite项目的作者thinkgem. 没有你我也不会更改这数据源非了恁大的劲,,,,嘻嘻嘻说多了. JeeSite ...

  3. SQL Server 列存储性能调优(翻译)

    原文地址:http://social.technet.microsoft.com/wiki/contents/articles/4995.sql-server-columnstore-performa ...

  4. 第14周翻译:SQL Server的阶梯安全级别2

    SQL Server的阶梯安全级别2:身份验证 源自:http://www.sqlservercentral.com/articles/Stairway+Series/109975/ 作者:Don K ...

  5. 第16周翻译:SQL Server中的事务日志管理,级别3:事务日志、备份和恢复

    源自: http://www.sqlservercentral.com/articles/Stairway+Series/73779/ 作者: Tony Davis, 2011/09/07 翻译:刘琼 ...

  6. SQL Server系统视图sys.master_files不能正确显示数据库脱机状态

    最近发现在SQL Server数据库(目前测试过SQL Server 2008, 2012,2014,2016各个版本)中,即使数据库处于脱机(OFFLINE)状态,但是sys.master_file ...

  7. SQL Server数据库连接,Web.config的正确配置 [转]

    http://database.51cto.com/art/201007/213289.htm 此文章主要介绍的是Web.config正确配置SQL Server数据库连接的实际擦步骤,在图5-6中, ...

  8. SQL Server如何正确的删除Windows认证用户

    在SQL Server数据库中,有时候会建立一些Windows认证的账号(域账号),例如,我们公司习惯给开发人员和Support同事开通NT账号权限,如果有离职或负责事宜变更的话,那么要如何正确的删除 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (12) -----第三章 查询之使用SQL语句

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 3-2使用原生SQL语句更新 问题 你想在实体框架中使用原生的SQL语句,来更新底层 ...

随机推荐

  1. 旧版本APP被开发人员下架,新版本重新上传依然显示被下架

    新接了一个项目,这个项目在苹果商城上面的版本已经被原来另外一家公司的开发人员下架.我们重新设计.开发.上传,申请加急审核,终于完成手动发布.但是发布成功后,新版本提示:被开发人员下架.以前虽然迭代开发 ...

  2. 常用function() 收集

    1.随机数生成函数(来源-微信支付demo案例) /** * * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public st ...

  3. VB常用字符串操作函数

    1. ASC(X),Chr(X):转换字符字符码 [格式]: P=Asc(X) 返回字符串X的第一个字符的字符码 P=Chr(X) 返回字符码等于X的字符 [范例]: (1)P=Chr(65) ‘ 输 ...

  4. VSTO PowerPoint 代码删除Shape后再恢复出现无法再次获取的问题

    做PowerPoint的VSTO插件项目,遇到个很奇怪的问题,当代码执行删除某些Shape时,没问题,但是操作Undo也就是恢复后,无法再次获取到之前删除的对象,这种情况只在Office2007中出现 ...

  5. iOS如何彻底避免数组越界

    我们先来看看有可能会出现的数组越界Crash的地方: ? 1 2 3 4 5 6 7 - (void)tableView:(UITableView *)tableView didSelectRowAt ...

  6. iOS中为什么block用copy属性

    1. Block的声明和线程安全Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC ...

  7. $.extend()和 $.fn.extend()

    1 $.extend()      jQuery.extend(): Merge the contents of two or moreobjects together into the first ...

  8. PostgresSQL的安装与基本命令使用

    安装与配置 yum install http://yum.postgresql.org/9.5/redhat/rhel-7-x86_64/pgdg-redhat95-9.5-2.noarch.rpm ...

  9. java 使用正则表达式过滤HTML中标签

    /** * 去掉文本中的html标签 * * @param inputString * @return */ public static String html2Text(String inputSt ...

  10. 通过挂载系统光盘搭建本地yum仓库的方法

    在CentOS系统中,我们常常会安装大量的软件,但许多软件包都存在需要依赖性,当然我们可以通过一一安装依赖包来完成安装,但对于有些软件包需要大量的依赖包,再一一安装起来会显得特别麻烦.接下来我们就来讲 ...