我的问题是 SQL Server 如何处理需要将比可用空间更多的数据量拉入缓冲区缓存的查询?此查询将包含多个连接,因此磁盘上不存在此格式的结果集,它需要编译结果。但即使在编译之后,它仍然需要比缓冲区缓存中的可用空间更多的空间。
我举一个例子。假设您有一个 SQL Server 实例,它有 6GB 的可用缓冲区缓存空间。我运行具有多个连接的查询,读取 7GB 的数据,SQL Server 如何能够响应此请求?它是否将数据临时存储在 tempdb 中?它失败了吗?它是否只从磁盘读取数据并一次编译段?
此外,如果我尝试返回 7GB 的总数据会发生什么,这是否会改变 SQL Server 处理它的方式?
我已经知道有几种方法可以解决这个问题,我只是好奇 SQL Server 在按规定运行时如何在内部处理此请求。
此外,我确信该信息存在于某处,但我一直没有找到它。
sql-server memory database-internals sql-server-2012 buffer-pool
对于下面的AdventureWorks示例数据库查询:
SELECT
P.ProductID,
CA.TransactionID
FROM Production.Product AS P
CROSS APPLY
(
SELECT TOP (1)
TH.TransactionID
FROM Production.TransactionHistory AS TH
WHERE
TH.ProductID = P.ProductID
ORDER BY
TH.TransactionID DESC
) AS CA;
Run Code Online (Sandbox Code Playgroud)
执行计划显示索引搜索的估计操作员成本为0.0850383 (93%) :
成本与使用的基数估计模型无关。
它不是简单地将Estimated CPU Cost和Estimated I/O Cost相加。它也不是指数搜索的一次执行成本乘以估计执行次数。
这个成本数字是如何得出的?
正如我在这个问题中提到的,我试图了解时钟指针的工作原理。只需在内存压力时将时钟指针移动,即可移除缓存条目或降低成本。
根据我所学到的,我现在尝试解释dm_os_memory_cache_clock_hands. 当我检查dm_os_memory_cache_clock_hands我的一台服务器(SQL Server 2016 SP1,32 RAM)时,我对我所看到的感到有些困惑。
在round_start_time为CACHESTORE_SQLCP 约为31小时,所以,我觉得,因为它需要一段时间来完成这一轮缓存中没有遭受大量的内存压力。另一方面,我看到last_tick_time每次刷新都会改变,所以手在移动。另一个奇怪的事实是这种removed_all_rounds_count情况也在发生变化。所以条目从缓存中删除。将clock_status始终暂停。在removed_last_round_count大约68000。
所以我的结论是有压力,CACHESTORE_SQLCP因为手在移动、removed_all_rounds_count变化和removed_last_round_count高。
这是对 dmv 的正确解释吗?
我不明白的是为什么round_start_time在 32GB 的服务器上如此之高,而且手一直在移动。
我使用以下脚本(我在Tigertoolbox 中找到的)转换last_tick_time为日期时间:
declare @ticks_per_ms bigint,@now DATETIME
select @ticks_per_ms=ms_ticks from sys.dm_os_sys_info
set @now=getdate()
CASE WHEN last_tick_time BETWEEN -2147483648 AND 2147483647 AND
@ticks_per_ms BETWEEN -2147483648 AND 2147483647
THEN DATEADD(ms, last_tick_time - @ticks_per_ms, @now)
WHEN last_tick_time/1000 BETWEEN -2147483648 …Run Code Online (Sandbox Code Playgroud) 在聊天讨论中出现的一个问题:
我知道散列连接救助在内部切换到某种嵌套循环。
SQL Server 为散列聚合救助做了什么(如果它可以发生的话)?
sql-server aggregate execution-plan database-internals hashing
前几天有人问我,如果 SQL Server 想要运行一个查询,而该查询被授予的内存多于实例可用的内存,会发生什么情况。我最初的想法是我可能会看到RESOURCE_SEMAPHORE等待并且查询永远不会开始。
我做了一些测试来试图找出答案。
我的实例以 4000MB RAM 启动:
EXEC sys.sp_configure N'max server memory (MB)', N'4000'
GO
RECONFIGURE WITH OVERRIDE
GO
Run Code Online (Sandbox Code Playgroud)
如果我然后运行我的(故意可怕的)查询:
USE StackOverflow
SELECT CONVERT(NVARCHAR(4000), u.DisplayName) AS DisplayName,
CONVERT(NVARCHAR(MAX), u.DisplayName) AS Disp2,
CONVERT(NVARCHAR(MAX), u.DisplayName) AS Disp3
FROM dbo.Users AS u
JOIN dbo.Posts p
ON LTRIM(u.DisplayName) = LTRIM(p.Tags)
WHERE u.CreationDate >= '2008-12-25'
AND u.CreationDate < '2010-12-26'
ORDER BY u.CreationDate;
Run Code Online (Sandbox Code Playgroud)
执行计划显示授予的内存为 732,008KB。
然后,我将实例可用的内存设置为低于此数字,然后重新启动实例:
EXEC sys.sp_configure N'max server memory (MB)', N'500' /* a value lower than the previous memory …Run Code Online (Sandbox Code Playgroud) 我正在阅读 Itzik 的书“查询 Microsoft SQL Server 2012”以及在互联网上阅读/观看不同的教育材料。我的目的是对数据库内部的工作方式有一个有用的理解。
我有点怀疑我无法解决 IAM 页面。由于我处于我理解的早期阶段,我可能需要那些对它有更好了解的人的额外帮助,所以如果我的怀疑看起来很荒谬,请原谅我。
在第 15 章“实施索引和统计”中出现了一个图像 - 如下所示 - 作为 IAM 页面的示例:

您可以通过红色箭头看到与相同程度相关的 16 页。这怎么可能?这是作者/编辑的错误吗?或者更有可能的是:有什么我没有正确理解的吗?
我的另一个问题与页面间隔有关。为什么它们不相邻?以最后一个extent为例,它将覆盖id为336到22642的页面,或者前一个,296到328的页面。
在这个问题中,我正在使用sys.sysobjects. 但是,提到的答案之一sys.system_objects。我只是想知道这些表之间有什么区别?
sys.objectssys.system_objectssys.sysobjectssysobjects 有更多的东西。
> SELECT count(*) FROM sysobjects;
2312
> SELECT count(*) FROM sys.system_objects;
2201
> SELECT count(*) FROM sys.objects;
> 111
SELECT count(*)
FROM sys.sysobjects
WHERE NOT EXISTS (
SELECT 1
FROM sys.system_objects
WHERE system_objects.object_id = sysobjects.id
);
> 111
Run Code Online (Sandbox Code Playgroud) 我看到很多内部视图,例如sys.syscomments调用CROSS APPLY OpenRowset(TABLE, oid). 我想知道这个函数是如何运作的以及它从什么地方读取的。让我们看一个例子TABLE SQLSRC,
OpenRowset(TABLE SQLSRC, o.id, 0)(o是sys.sysschobjs$)OpenRowset(TABLE SQLSRC, c.object_id, c.column_id)(c是sys.computed_columns)OpenRowset(TABLE SQLSRC, p.object_id, p.procedure_number)(p是sys.numbered_procedures)OpenRowset(TABLE SQLSRC, o.object_id, 0)(o是sys.all_objects)OpenRowset(TABLE SQLSRC, o.id, 0)(o是sys.sysschobjs$)看起来它正在存储程序的源代码,但在内部它们读取的是TABLE SQLSRC什么,又是什么?我猜这是一个外线键值存储?
我知道我可以使用object_definition(这是sys.sql_modules内部调用),但我想了解数据库的工作方式以及存储位置。
而且,不仅SQLSRC有TABLE对以下内容的引用,
ACTIVE_TRANSACTIONS
ALUCOUNT
APRC_EVENT
BLOB_CONTAINER_ACCESSOR
BUILTINPERMISSIONS
CFGPROP …Run Code Online (Sandbox Code Playgroud) 下面的 EXCEPT 查询生成一个带有看似无目的投影的逻辑计划。INTERSECT 也会发生这种情况。
投影的目的是什么?例如,是否有不同的 EXCEPT 查询,其中外投影会指定某些内容?
询问:
use AdventureWorks2017
select p.ProductId
from Production.Product as p
except
select pinv.ProductID
from Production.ProductInventory as pinv
option (recompile, querytraceon 8605, querytraceon 3604)
Run Code Online (Sandbox Code Playgroud)
转换树:
LogOp_Select
LogOp_GbAgg OUT(QCOL: [p].ProductID,) BY(QCOL: [p].ProductID,)
LogOp_Project -- << ?? PASSIVE PROJECTION ??
LogOp_Project
LogOp_Get TBL: Production.Product(alias TBL: p) Production.Product TableID=482100758 TableReferenceID=0 IsRow: COL: IsBaseRow1000
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
ScaOp_Exists
LogOp_Select
LogOp_Project
LogOp_Get TBL: Production.ProductInventory(alias TBL: pinv) Production.ProductInventory TableID=914102297 TableReferenceID=0 IsRow: COL: IsBaseRow1001
AncOp_PrjList
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [p].ProductID
ScaOp_Identifier QCOL: …Run Code Online (Sandbox Code Playgroud) 当我在 SQL Server 中使用大对象 (LOB) 数据类型的变量时,整个变量是否始终保存在内存中?即使是2GB大小?
sql-server ×10
memory ×2
aggregate ×1
blob ×1
buffer-pool ×1
except ×1
hashing ×1
memory-grant ×1
optimization ×1