博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL Server 优化器特性导致的内存授予相关BUG
阅读量:7296 次
发布时间:2019-06-30

本文共 1137 字,大约阅读时间需要 3 分钟。

原文:

我们有时会遇到一些坑,要不填平,要不绕过.这里为大家介绍一个相关SQL Server优化器方面的特性导致内存授予的相关BUG,及相关解决方式,也顺便回答下邹建同学的相关疑问.

 

问题描述

一个简单的查询消耗了匪夷所思的内存.(邹建同学发现的)

Code

create table test_mem(id int identity(1,1) primary key,itemid int not null,date datetime not null,str1 varchar(max) null)INSERT test_mem( itemid,date )    SELECT TOP(1000)        ABS(CHECKSUM(NEWID())) % 200,        DATEADD(day, CHECKSUM(NEWID()) % (3 * 360), GETDATE())    FROM sys.all_columns A, sys.all_columns B    go 100select * from  test_mem where itemid=28 order by date

执行代码后执行计划如图1-1

                                                图1-1

可以看出如此小的数据集排序居然消耗如此恐怖的内存数据量级,这样简单查询如果数据量再大些完全可能严重影响吞吐.

 

问题分析:通过执行计划我们发现只是一个简单的聚集索引扫描加上一个排序.问题就出现在聚集索引扫描上,通过语义分析我们发现我们的那个Itemid=28也包含在聚集索引扫描中过滤了,但优化器在做内存评估时并未注意到此状况,还是按照全表的相关内存大小评估的.

我们可以根据行大小大概算出优化器”认为”的数据大小.

Select 100000.0*4051.0/1024.0/1024.0 (约等于386MB!)

原来优化器以为他要对386MB的数据排序…

问题总结:优化器在做聚集索引扫描时同时为我们做了Filter过滤,但对接下来的内存评估时确忽略了运算符中的过滤.致使内存评估出现严重问题.

 

解决:了解了问题点后解决就简单了.在去年6月份的Pass分享中我曾经提过Filter运算符,我们只需让他在我们的执行计划中重现即可.

Trace Flag 9130 可以使得这个运算符可以重现.

Code

select * from  test_mem where itemid=28 order by dateoption(querytraceon 9130)

 

可以通过执行计划看出,内存授予正常,如图1-2所示

                                                 图1-2

注:此坑一旦踩上影响着实不小,看到的朋友请扩散.

后记:此问题我已经反应给微软的CSS团队.

 

转载地址:http://jownm.baihongyu.com/

你可能感兴趣的文章
阿里云容器服务新增支持Kubernetes编排系统,性能重大提升
查看>>
[Spring boot] Spring boot + JPA 基本架构,完成CRUD
查看>>
【全栈项目上线(vue+node+mongodb)】06.nodejs服务上线(生产环境前后分离的vue项目中怎么解决跨域问题)...
查看>>
【288天】每日项目总结系列026(2017.11.20)
查看>>
git代码回滚的几种方式
查看>>
vue.js组件学习(上)
查看>>
学习开发自己的composer包,并使用GitHub实时更新到Packagist
查看>>
vue学习笔记(三)
查看>>
Mac 勿扰模式周期性开关闭功能实现脚本
查看>>
sublime中利用正则批量修改数据
查看>>
GitBook关联GitHub
查看>>
系统单据号生成规则推荐
查看>>
[译] NSCollectionView 入门教程
查看>>
【vuejs路由】vuejs 路由基础入门实战操作详细指南
查看>>
express 源码阅读(全)
查看>>
获取height固定折叠元素真实高度方法
查看>>
文件寄生——寄生虫自体繁衍的道路
查看>>
【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting)
查看>>
Redis 服务器管理相关命令
查看>>
阿里云前端周刊 - 第 13 期
查看>>