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

本文涉及的产品
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
相关文章
|
6月前
|
缓存 关系型数据库 MySQL
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
265 0
|
5月前
|
SQL 安全 数据挖掘
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
Elasticsearch聚合查询用于复杂数据分析,包括统计空值率。示例展示了如何计算字段`my_field`非空非零文档的百分比。查询分为三步:总文档数计数、符合条件文档数计数及计算百分比。聚合概念涵盖度量、桶和管道聚合。脚本在聚合中用于动态计算。常见聚合类型如`sum`、`avg`、`date_histogram`等。组合使用可实现多值统计、嵌套聚合和空值率计算。[阅读更多](https://zhangfeidezhu.com/?p=515)
294 0
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
|
5月前
|
NoSQL BI MongoDB
深入理解 MongoDB 条件操作符:优化查询、精准筛选、提升性能
深入理解 MongoDB 条件操作符:优化查询、精准筛选、提升性能
105 1
|
5月前
|
SQL Java 数据库连接
大事件后端项目28------文章分类列表查询(条件分页)
大事件后端项目28------文章分类列表查询(条件分页)
|
6月前
|
NoSQL MongoDB 数据库
通过优化索引以消除 MongoDB 中的 "查询目标已超过1000个扫描对象/返回的文档数" 警告
MongoDB NoSQL数据库在处理复杂查询时可能出现“查询目标已超过1000个扫描对象/返回的文档数”警告。文章分析了该问题,展示了一个示例集合和相关索引,并提供了查询示例。通过`explain`命令发现查询未有效利用索引。解决方案是遵循ESR规则,创建新索引从而优化查询并消除警告。
163 1
|
存储 缓存 数据库
提高Djang查询速度的9种方法
在Web应用程序中,数据库查询是一个关键的环节。优化数据库查询可以显著提高应用程序的性能和响应速度。Django作为一个高度可扩展的Web框架,提供了多种方式来优化数据库查询。本文将介绍一些常用的Django数据库查询优化技巧,从入门到精通,帮助您构建高效的应用程序。
149 1
|
SQL 分布式计算 MaxCompute
一次性查询一张表所有字段的空值率
一次性查询一张表所有字段的空值率
1625 2
|
数据采集 数据可视化 数据挖掘
如何筛选和过滤ARWU网站上的大学排名数据
ARWU网站(ShanghaiRanking's Academic Ranking of World Universities)是一个公认的全球大学排名的先驱和最值得信赖的大学排名之一。它每年发布世界前1000所研究型大学的排名,基于透明的方法论和客观的第三方数据。ARWU网站上的大学排名数据可以为高考考生、专业选择、就业指导、行业发展等提供有价值的参考信息。
如何筛选和过滤ARWU网站上的大学排名数据
|
PHP
php清洗数据实战案例(4):按照关联数组相同值名称进行筛选后对不同的指标予以合并计算的解决方案
php清洗数据实战案例(4):按照关联数组相同值名称进行筛选后对不同的指标予以合并计算的解决方案
65 0
|
移动开发 JavaScript 算法
如何实现动态内容条件筛选
这两天看了一下后端给的接口文档,每一个都要求筛选,而且这个筛选还是多条件的,还是不能固定的,要求根据用户的输入然后筛选,我之前的实现大概是这样子,当用户想要筛选的时候就去检索条件,并输入相关的内容进行筛选