表中的每一行都有一个系统列 ctid,其类型tid表示该行的物理位置:
Run Code Online (Sandbox Code Playgroud)create table t(id serial); insert into t default values; insert into t default values;
Run Code Online (Sandbox Code Playgroud)select ctid , id from t;ctid | ID :---- | -: (0,1) | 1 (0,2) | 2
dbfiddle在这里
从ctid最合适的类型(例如integer,bigint或numeric(1000,0))中获取页码的最佳方法是什么?
在我能想到的唯一的办法是非常难看。
在谷歌搜索时,我发现了一些相互矛盾的信息。
某些站点指出,当没有为数据留下物理内存时,SQL Server 会将现有数据移动到 TEMPDB(请参阅:SQL Server:揭秘 TempDb 和建议)。
但是其他站点声明,当没有足够的物理内存时,操作系统可以使用 PAGE FILE 并将数据从物理内存移到它(请参阅SQL Server 的页面文件)。
我想知道当 SQL Server 物理内存不足时,它会在哪里写入数据?到 tempdb 还是到 OS Page 文件?或者两者都有?
使用页面压缩 ( ALTER INDEX IX1 REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE))重建其 SQL Server 索引后,后续重建(如某些维护脚本超过某个碎片阈值所做的那样)是否需要再次指定数据压缩?否则索引会被有效地解压吗?
我最近听说聚集索引中的数据页不是连续存储的。这是真的?
也许数据页通常是连续存储的,但规则有一些例外?或者我听错了,数据页总是连续存储的。
非常感谢。
我继续在许多论坛和许多博客上看到一个页面的组成如下所示: 页面大小:16 x 512B = 8192B 页眉:= 96B 最大 In_Row 行:= 8060B
这留下 (8192 - 96 - 8060)B = 36B。
好的,这是合乎逻辑且正确的。我的问题是:为什么那么多人说剩下的36B是留给slot array的?
显然,插槽数组在页面上每行给出 2B;所以,它可以小到 2B,大到 1472B:
2B:1 行 * 2B = 2B
1472B:8096B = n*9B(带开销的最小行大小……想想单个 TINYINT 列)+ n*2B(每行槽阵列成本)=> 8096 = 11n => n = 8096 / 11 = 736。
736*2B = 1472B。
由于 14B 版本标签,这使我达到 20。
USE master ;
GO
CREATE DATABASE test ;
GO
USE test ;
GO
ALTER DATABASE test
SET ALLOW_SNAPSHOT_ISOLATION ON ;
GO
ALTER DATABASE test …Run Code Online (Sandbox Code Playgroud) sql-server-2008 storage-engine data-pages database-internals
我创建了下表:
CREATE TABLE dbo.TestStructure
(
id INT NOT NULL,
filler1 CHAR(36) NOT NULL,
filler2 CHAR(216) NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
然后创建了一个聚集索引:
CREATE CLUSTERED INDEX idx_cl_id
ON dbo.TestStructure(id);
Run Code Online (Sandbox Code Playgroud)
接下来我用 30 行填充它,每个大小为 256 字节(基于表声明):
DECLARE @i AS int = 0;
WHILE @i < 30
BEGIN
SET @i = @i + 1;
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (@i, 'a', 'b');
END;
Run Code Online (Sandbox Code Playgroud)
现在根据我在“Training Kit (Exam 70-461): Querying Microsoft SQL Server 2012 (Itzik Ben-Gan)”一书中读到的信息:
SQL Server 在内部以页为单位组织数据文件中的数据。一个页面是一个 8 KB 的单位,属于一个单一的对象;例如,到表或索引。页是读取和写入的最小单位。页面被进一步组织成范围。一个区由八个连续的页面组成。一个范围内的页面可以属于单个对象或多个对象。如果页面属于多个对象,则该范围称为混合范围;如果页面属于单个对象,则该范围称为统一范围。SQL Server 将对象的前八页存储在混合区中。当对象超过八页时,SQL Server 会为此对象分配额外的统一区。通过这种组织,小物体浪费的空间更少,大物体的碎片化程度也更低。
所以这里我有第一个混合范围 …
我的印象是,如果我要对DATALENGTH()表中所有记录的所有字段求和,我将得到表的总大小。我错了吗?
SELECT
SUM(DATALENGTH(Field1)) +
SUM(DATALENGTH(Field2)) +
SUM(DATALENGTH(Field3)) TotalSizeInBytes
FROM SomeTable
WHERE X, Y, and Z are true
Run Code Online (Sandbox Code Playgroud)
我在下面使用了这个查询(我从网上得到的表大小,聚集索引,所以它不包括 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 (nolock)
INNER JOIN
sys.schemas s with (nolock) ON s.schema_id = t.schema_id
INNER JOIN
sys.indexes i with (nolock) ON t.OBJECT_ID …Run Code Online (Sandbox Code Playgroud) sql-server data-pages clustered-index metadata database-internals
我为 .ndf 创建了太多辅助数据文件 (.ndf) tempdb。要删除多余的文件,我需要清空文件(内容将移动到其他文件):
DBCC SHRINKFILE('tempdbfile8', EMPTYFILE);
Run Code Online (Sandbox Code Playgroud)
然后删除文件:
ALTER DATABASE tempdb REMOVE FILE tempdbfile8;
Run Code Online (Sandbox Code Playgroud)
但是EMPTYFILE命令返回错误:
DBCC SHRINKFILE: Page 8:41920 could not be moved because it is a work table page.
Msg 2555, Level 16, State 1, Line 2
Cannot move all contents of file "tempdbfile8" to other places to complete the emptyfile operation.
Run Code Online (Sandbox Code Playgroud)
不用担心,我只需要找到使用此页面的对象即可:
DBCC TRACEON (3604)
DBCC PAGE(2,8,41920) --dbid=2, fileid=8, pageid=41920
Run Code Online (Sandbox Code Playgroud)
该命令返回了很多信息,其中的object_id。但:
Metadata: ObjectId = 0
Run Code Online (Sandbox Code Playgroud)
我不知道该怎么办。什么猫阻止了这个页面被移动?如何定位该对象、进程、会话或其他任何内容?任何帮助将不胜感激,但请注意保持原样或删除其他文件不是解决此问题的有效方法;)。
编辑:
我正在删除这些文件,因为我们曾经遵循“最佳实践”,即为每个处理器内核创建一个文件(相同的初始大小,相同的增长率)。但据我所知,在遇到争用问题之前,没有必要在同一设备上创建额外的 tempdb 文件。在我们的例子中,这是有道理的,因为我们打开了MPIO,并且存储设备可以处理 4 个路径。但是有一个错误,我们最终得到了 …
我创建了一个包含 650 个 Numeric(19,4) 列的表。当我打开页面压缩时,通过运行
ALTER TABLE fct.MyTable REBUILD WITH (DATA_COMPRESSION = PAGE);
Run Code Online (Sandbox Code Playgroud)
我得到
消息 1975,级别 16,状态 1
索引“PK_Mytable”行长度超过了“8060”字节的最大允许长度。
但是 650 乘以 9 字节仅为 5850 字节,这与规定的 8060 字节的限制相去甚远。
服务器运行的是 Windows 2012 r2 和 SQL Server 2016 SP1 CU2
使用页面压缩时的行开销是多少?
这是一些代码来显示我的意思:
/* test script to demo MSG 1975 */
DECLARE @sql NVARCHAR(max)='', @i INT =0
drop table if exists dbo.mytable;
SET @sql = 'Create table dbo.Mytable (MyTableID bigint not null
identity(1,1) primary key clustered, '
WHILE @i < 593 BEGIN
SET …Run Code Online (Sandbox Code Playgroud) 有没有办法计算填充 SQL Server 中 8 KB 页的数据量并创建一个完全填充一页的表?这篇博文中介绍了这种表格。
data-pages ×10
sql-server ×7
compression ×2
index ×2
cast ×1
datafile ×1
datatypes ×1
dbcc ×1
memory ×1
metadata ×1
postgresql ×1
t-sql ×1
tempdb ×1