Questions tagged «database-internals»

有关数据库引擎内部工作的技术问题。

4
可以参与SET操作的最大局部变量数是多少?
我有一个包含业务逻辑的存储过程。在它里面,我有大约1609个变量(不要问我为什么,这就是引擎的工作原理)。我尝试将SET一个变量转换为所有其他变量的串联值。结果是在创建过程中出现错误: 消息8631,级别17,状态1,过程XXX,行YYY内部错误:已达到服务器堆栈限制。请在查询中寻找潜在的深层嵌套,并尝试简化它。 我发现该错误是由于我需要在SET操作中使用的变量数量引起的。我可以将作业一分为二来执行。 我的问题是这方面有限制吗?我检查了一下,但是没有找到。 我们检查了此KB中描述的错误,但这不是我们的情况。我们CASE在代码内不使用任何表达式。我们使用该临时变量准备必须使用CLR函数替换的值的列表。我们将SQL Server更新为SP3 CU6(最新),但是仍然遇到该错误。

2
DATALENGTH的总和与sys.allocation_units中的表大小不匹配
我的印象是,如果我将DATALENGTH()一个表中所有记录的所有字段的总和求和,我将得出该表的总大小。我错了吗? SELECT SUM(DATALENGTH(Field1)) + SUM(DATALENGTH(Field2)) + SUM(DATALENGTH(Field3)) TotalSizeInBytes FROM SomeTable WHERE X, Y, and Z are true 我在下面使用此查询(我从网上获得此查询来获取表大小,仅聚集索引,因此它不包含NC索引)来获取数据库中特定表的大小。出于计费目的(我们按部门使用的空间量向部门收取费用),我需要找出此表中每个部门使用的空间。我有一个查询,用于标识表中的每个组。我只需要弄清楚每个小组要占用多少空间。 由于VARCHAR(MAX)表中的字段,每行空间可能会波动很大,因此我不能只取平均大小*部门的行数比率。当我使用上述DATALENGTH()方法时,我只能获得下面查询中使用的总空间的85%。有什么想法吗? SELECT s.Name AS SchemaName, t.NAME AS TableName, p.rows AS RowCounts, (SUM(a.total_pages) * 8)/1024 AS TotalSpaceMB, (SUM(a.used_pages) * 8)/1024 AS UsedSpaceMB, ((SUM(a.total_pages) - SUM(a.used_pages)) * 8)/1024 AS UnusedSpaceMB FROM sys.tables t with …

1
高PAGELATCH_ *和WRITELOG等待。他们有关系吗?
我们看到非常高的PAGELATCH_EX和PAGELATCH_SH等待类型以及较高的WRITELOG等待。我已经诊断出导致PAGELATCH等待的查询,并且可以通过降低插入由IDENTITY值定义的繁忙集群主键的插入率来消除它们。我知道这种现象被称为最后一页插入闩锁争用。 但是我的问题是,当插入新记录时,SQL Server是否在缓冲区页面上执行排他的PAGELATCH_EX,将记录​​插入缓冲区页面,将记录写入事务日志,然后释放排他的PAGELATCH_EX,详情如下:https:// www.microsoft.com/zh-cn/download/details.aspx?id=26665第24页。还是先将记录写到事务日志中,然后再进行PAGELATCH_EX的详细说明,“解决高度并发的PAGELATCH争用-插入工作负载-背景信息SQLCAT的指南:关系引擎 如果将记录写到锁存机制之外的日志中,那么我可以排除对磁盘的慢速写入,这是导致PAGELATCH等待时间较长的原因。但是,如果保持闩锁直到记录难以记录,那么我应该考虑WRITELOG。 同样,具有多个非聚集索引会导致PAGELATCH_ *锁存器保持更长的时间,即,如果表具有聚簇且多个非聚簇索引被同时添加并释放到每个索引缓冲区页的锁存器? 更新1 阅读confio-sql-server-writelog-wait幻灯片2和一般的WAL体系结构之后。现在,我的理解是,两本白皮书中详细介绍的“记录行已被修改的日志条目”步骤是指SQL Server在事务日志缓存(而不是磁盘)中记录更改。一旦事务完成或缓冲区已满,所有记录将立即刷新到磁盘。

2
为什么禁用聚集索引会使表不可访问?
禁用索引后,定义保留在系统目录中,但不再使用。SQL Server不维护索引(当表中的数据更改时),并且该索引不能用于满足查询。如果禁用了聚集索引,则整个表将无法访问。 为什么不能直接从丢弃B树的表中访问数据?(最有可能通过逐行扫描表)是否比使数据完全不可访问更合适? 这是一个纯粹的理论问题-我绝对不会这样做。这不是一个场景,也不是一个要做的事情,我只是想知道事情为什么这样发展,将其视为内部问题。


3
在缓冲区缓存中没有足够空间的情况下,SQL Server如何处理查询的数据?
我的问题是,SQL Server如何处理需要将比可用空间更多的数据拉入缓冲区缓存的查询?该查询将包含多个联接,因此结果集在磁盘上已经不存在该格式的结果,因此需要编译结果。但是即使在编译之后,它仍然需要比缓冲区高速缓存中可用空间更多的空间。 我举一个例子。假设您有一个SQL Server实例,总共有6GB的可用缓冲区高速缓存空间。我运行具有多个联接的查询,该联接读取7GB数据,SQL Server如何响应此请求?是否将数据临时存储在tempdb中?它会失败吗?它是否仅执行一次从磁盘读取数据并一次编译段的操作? 此外,如果我尝试返回7GB的总数据会发生什么,这是否会改变SQL Server的处理方式? 我已经知道解决此问题的几种方法,我很好奇SQL Server在按要求运行时如何在内部处理此请求。 另外,我确定此信息存在于某处,但我一直没有找到它。

1
将数据加载到临时表中时获得最少的日志记录
即使在阅读了《数据加载性能指南》之后,我仍然不确定是否有必要将TABLOCK表提示添加到一个空的临时表中,该临时表由一个聚集索引定义,以便获得最少的日志记录。 显然,临时表是在TempDB中创建的,该表以SIMPLE恢复模式运行,因此我本以为它是最小化日志记录的理想选择,但是我找不到找到该表的方法。 临时表是否可以作为最少日志记录的候选表?如果这样,是否值得为永久表推荐添加TABLOCK提示?

1
测量计划驱逐
我们有一个SQL Server 2016 SP1,最大内存设置为24GB。 该服务器具有大量编译,其中只有10%的编译来自临时查询。因此,新编译的计划应存储在计划缓存中,但计划缓存的大小不会增加(约3.72GB)。 我怀疑本地内存压力会导致从缓存中删除计划。计划缓存压力限制为5GB。(0-4GB的可见目标内存的75%+ 4GB-64GB的可见目标内存的10%+> 64GB的可见目标内存的5%)。当缓存存储达到压力限制的75%时,应从缓存中删除计划。就我而言,5 GB的75%为3.75 GB。因此,这可能是高编译率的原因。 有没有一种方法可以测量(性能,扩展事件等)从缓存中删除计划?这样我就可以确定本地内存压力确实是高编译的原因吗?

1
指数寻求运营商成本
对于下面的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; 执行计划显示针对Index Seek的估计运营商成本为0.0850383(93%): 成本与使用的基数估计模型无关。 这不是“ 估计的CPU成本”和“ 估计的I / O成本”的简单相加。一次执行索引搜索的成本也不乘以估计的执行次数。 这个费用数字是如何得出的?

1
了解IAM页面:范围间隔
我正在阅读Itzik的书《查询Microsoft SQL Server 2012》,以及在互联网上阅读/观看不同的教学材料。我的目的是对数据库内部如何工作有一个有益的了解。 我有一个小小的疑问,我无法解决有关IAM页面的问题。由于我尚处于了解的初期,因此也许我需要那些了解情况更好的人的额外帮助,因此,如果我的疑问似乎很可笑,请原谅我。 在第15章“实现索引和统计信息”中,出现了一个图像-如下图所示-作为IAM页面的示例: 您可以通过红色箭头看到与同一范围相关的16页内容。那怎么可能?是作者/编辑的错误吗?还是更有可能的:我是否有一些不正确的理解? 我的另一个问题与页面间隔有关。为什么它们不连续?以最后一个范围为例,它将覆盖ID为336至22642或前一个ID为296至328的页面。

1
联接的虚拟表中的NEWID()导致意外的交叉应用行为
我的实际工作查询是一个内部联接,但是这个带有交叉联接的简单示例似乎几乎总是重现了该问题。 SELECT * FROM ( SELECT 1 UNION ALL SELECT 2 ) AA ( A ) CROSS JOIN ( SELECT NEWID() TEST_ID ) BB ( B ) 对于我的内部联接,我有很多行,我使用NEWID()函数向每个行添加了一个GUID,对于10行中的大约9行,与2行虚拟表的乘法产生了预期的结果,只有2个副本相同的GUID,而十分之1会产生不同的结果。至少可以说这是出乎意料的,这让我很难在测试数据生成脚本中找到此错误。 如果使用非确定性getdate和sysdatetime函数查看以下查询,您将不会看到此信息,无论如何我都不会看到-我总是在两个最终结果行中看到相同的datetime值。 SELECT * FROM ( SELECT 1 UNION ALL SELECT 2 ) AA ( A ) CROSS JOIN ( SELECT GETDATE() TEST_ID …

1
为什么Set Returning Function(SRF)在FROM子句中运行较慢?
这是数据库内部的问题。我使用的是PostgreSQL 9.5,我想知道为什么在FROM子句中设置返回函数(SRF)(也称为表值函数(TVF))运行速度较慢,例如当我执行这些命令时, CREATE TABLE foo AS SELECT * FROM generate_series(1,1e7); SELECT 10000000 Time: 5573.574 ms 它总是比 CREATE TABLE foo AS SELECT generate_series(1,1e7); SELECT 10000000 Time: 4622.567 ms 这里是否可以制定一条通用规则,以便我们应该始终在FROM子句之外运行Set-Returning Functions ?

2
SQL Server 2014压缩和最大行大小
我需要创建一个包含许多十进制(26,8)列的宽非规范化表(少于1024列限制,大多数列将为null或零)。我知道每行限制8060字节,因此我尝试创建具有页面压缩功能的表。下面的代码创建表,插入一行并查询行大小。行大小远低于限制,但是如果我尝试向表中再添加一个小数(26,8)列,操作将失败,并显示错误“创建或更改表't1'失败,因为最小行大小为8074,包括1256”内部开销字节。”。有什么方法可以创建具有这么多列的单个表吗? drop table t1 GO create table t1(c1 decimal(26, 8) null) with (data_compression = page) GO declare @i int = 2; declare @sql varchar(100); while @i <= 486 begin set @sql = 'alter table t1 add c' + convert(varchar, @i) + ' decimal(26, 8) null'; execute (@sql); set @i += …

1
为什么要进行更多(以及数量不等的)逻辑读取并预读(预取)?
在我的SQL Server中创建tpch数据库后,我尝试了以下查询: set statistics io on DBCC DROPCLEANBUFFERS; select top 100 * from dbo.lineitem order by l_partkey; 表lineitem在l_partkey上具有非聚集索引。我多次发出上述查询,发现每次的逻辑读取都不同: Table 'lineitem'. Scan count 1, logical reads 1019, physical reads 4, read-ahead reads 1760, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'lineitem'. Scan count 1, logical …


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.