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

 更新时间:2016年11月17日 16:32:50   作者:Wei.T  
今天通过本文给大家介绍在SQL Server上关于indexing的一个特定的性能问题,本文给大家介绍的非常详细,具有参考借鉴价值,感兴趣的朋友可以参考下

原文地址:http://www.sqlpassion.at/archive/2014/04/08/improving-query-performance-by-using-correct-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)的操作了。

相关文章

  • SQL Server 2012 搭建数据库AlwaysOn(数据库高可用集群)

    SQL Server 2012 搭建数据库AlwaysOn(数据库高可用集群)

    这篇文章主要介绍了SQL Server 2012 搭建数据库AlwaysOn(数据库高可用集群),需要的朋友可以参考下
    2023-05-05
  • 分组后分组合计以及总计SQL语句(稍微整理了一下)

    分组后分组合计以及总计SQL语句(稍微整理了一下)

    这篇文章主要介绍了分组后分组合计以及总计SQL语句,需要的朋友可以参考下
    2017-02-02
  • 配置SQL Server数据库恢复模式(2种方法)

    配置SQL Server数据库恢复模式(2种方法)

    这篇文章主要介绍了配置SQL Server数据库恢复模式的两种方法,需要了解的朋友可以参考下
    2015-10-10
  • SQL的Join使用图解教程

    SQL的Join使用图解教程

    对于SQL的Join,在学习起来可能是比较乱的。我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚
    2012-08-08
  • MSSQL存储过程的功能和用法详解

    MSSQL存储过程的功能和用法详解

    Microsoft SQL Server(MSSQL)是一个关系型数据库管理系统,它支持各种数据操作和查询功能,其中,存储过程是MSSQL中非常重要的一个功能,在这个章节中,我们将详细介绍MSSQL存储过程的功能和用法
    2023-12-12
  • sql 函数大全 比较常用的一些函数整理

    sql 函数大全 比较常用的一些函数整理

    学习sqlserver的朋友,可以参考下,掌握这些函数可以方便的对字段的字符进行处理。
    2010-04-04
  • sql server性能调优 I/O开销的深入解析

    sql server性能调优 I/O开销的深入解析

    这篇文章主要给大家介绍了关于sql server性能调优 I/O开销的相关资料,文中通过示例代码以及图片介绍的非常详细,对大家的理解和学习具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • 浅析SQL语句中GROUP BY的用法

    浅析SQL语句中GROUP BY的用法

    “Group By”从字面意义上理解就是根据“By”指定的规则对数据进行分组,所谓的分组就是将一个“数据集”划分成若干个“小区域”,然后针对若干个“小区域”进行数据处理。
    2014-08-08
  • SQL Server数据库备份加密的方法详解

    SQL Server数据库备份加密的方法详解

    在数据即资产的今天,保护数据库备份免受未授权访问是至关重要的,SQL Server提供了强大的安全特性,包括对数据库备份进行加密的能力,本文将深入探讨如何在SQL Server中实现数据库的自定义数据备份加密,需要的朋友可以参考下
    2024-08-08
  • 教你几种在SQLServer中删除重复数据方法

    教你几种在SQLServer中删除重复数据方法

    数据库的使用过程中由于程序方面的问题有时候会碰到重复数据,重复数据导致了数据库部分设置不能正确设置……
    2010-04-04

最新评论