使用正确的筛选参数来提高查询性能

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介:

问题描述

假设下列的简单查询,在你的日常SQL Server里,这样的查询你已经看到过几百遍了:

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

用那个简单查询,我们请求在特定年份特定月份里的销售信息。并不复杂。遗憾的是这个查询性能很差——即使在OrderDate列使用了非聚集索引。当你查看执行计划时,你会看到查询优化器选择了在OrderDate列上的非聚集索引,但遗憾的是SQL Server进行的索引的全扫描,而不是高效的查找操作。

 

这真不是SQL Server的局限性,而是关系数据库的工作和思考方式:)只要你在索引列上使用了表达式(函数调用,计算)(即所谓的筛选参数(Search Argument),数据库引擎必须去扫描那个索引,而不是进行查找操作。

解决方法

在执行计划里为了获得可扩展的查找操作,你必须要换种方式重写你的查询来避免DATEPART函数的调用: 

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

从重写的查询可以看到,查询返回同样的结果,但我们已经剔除了DATEPART函数的调用。当你查看执行计划时,你会看到SQL Server进行了查找操作——在那个情况下,这个是所谓的局部范围扫描(Partial Range Scan):SQL Server查找到第1个值,然后扫描到请求范围的最有值。如果你想在索引列上下文调用函数,你必须保证在查询里,这些函数调用的执行在你列的右侧。我们来看一个具体的例子。下面查询把CreditCardID索引列转化为CHAR(4)数据类型:

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

当你仔细看执行计划时,你会看到SQL Server再次扫描整个非聚集索引。如果你的表越来越大,这是真不能扩展的。如果你在查询里在你索引列的右侧执行转化,你就可以在索引列上剔除函数调用,SQL Server就可以进行查找操作:

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

小结

从这篇文章里,你可以看到,在你的索引列里不直接调用任何函数或间接调用函数是非常重要的。不然的话SQL Server会扫描你的索引,而不是进行高效的查找操作。而且当你表越来越大时,扫描从不扩展。

本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/4646384.html,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
5月前
|
索引
Elasticsearch 精确查询:术语查询、多术语查询、主键查询、范围查询、存在查询、前缀查询、正则查询与通配符查询
Elasticsearch 精确查询:术语查询、多术语查询、主键查询、范围查询、存在查询、前缀查询、正则查询与通配符查询
|
5月前
|
SQL DataWorks 数据处理
DataWorks产品使用合集之假设存在时间戳字段: 假设源表有一个记录数据更新时间的字段,如何设置过滤条件
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
26 1
|
4月前
|
分布式计算 BI MaxCompute
SQL 能力问题之输出聚合的维度列的名称,如何解决
SQL 能力问题之输出聚合的维度列的名称,如何解决
|
5月前
|
SQL 安全 数据挖掘
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
Elasticsearch聚合查询用于复杂数据分析,包括统计空值率。示例展示了如何计算字段`my_field`非空非零文档的百分比。查询分为三步:总文档数计数、符合条件文档数计数及计算百分比。聚合概念涵盖度量、桶和管道聚合。脚本在聚合中用于动态计算。常见聚合类型如`sum`、`avg`、`date_histogram`等。组合使用可实现多值统计、嵌套聚合和空值率计算。[阅读更多](https://zhangfeidezhu.com/?p=515)
298 0
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
|
5月前
|
NoSQL BI MongoDB
深入理解 MongoDB 条件操作符:优化查询、精准筛选、提升性能
深入理解 MongoDB 条件操作符:优化查询、精准筛选、提升性能
128 1
|
6月前
|
NoSQL MongoDB 数据库
通过优化索引以消除 MongoDB 中的 "查询目标已超过1000个扫描对象/返回的文档数" 警告
MongoDB NoSQL数据库在处理复杂查询时可能出现“查询目标已超过1000个扫描对象/返回的文档数”警告。文章分析了该问题,展示了一个示例集合和相关索引,并提供了查询示例。通过`explain`命令发现查询未有效利用索引。解决方案是遵循ESR规则,创建新索引从而优化查询并消除警告。
181 1
|
6月前
|
缓存 索引
7.过滤查询
7.过滤查询
|
存储 缓存 数据库
提高Djang查询速度的9种方法
在Web应用程序中,数据库查询是一个关键的环节。优化数据库查询可以显著提高应用程序的性能和响应速度。Django作为一个高度可扩展的Web框架,提供了多种方式来优化数据库查询。本文将介绍一些常用的Django数据库查询优化技巧,从入门到精通,帮助您构建高效的应用程序。
154 1
|
SQL 分布式计算 MaxCompute
一次性查询一张表所有字段的空值率
一次性查询一张表所有字段的空值率
1723 2
|
数据采集 数据可视化 数据挖掘
如何筛选和过滤ARWU网站上的大学排名数据
ARWU网站(ShanghaiRanking's Academic Ranking of World Universities)是一个公认的全球大学排名的先驱和最值得信赖的大学排名之一。它每年发布世界前1000所研究型大学的排名,基于透明的方法论和客观的第三方数据。ARWU网站上的大学排名数据可以为高考考生、专业选择、就业指导、行业发展等提供有价值的参考信息。
如何筛选和过滤ARWU网站上的大学排名数据