我有一个包含 75 亿行和 5 个索引的大表。当我删除大约 1000 万行时,我注意到非聚集索引似乎增加了它们存储的页数。
我写了一个查询dm_db_partition_stats
来报告页面中的差异(之后 - 之前):
索引1是聚集索引,索引2是主键。其他的都是非聚集的和非唯一的。
为什么那些非聚集索引上的页面会增加?
我预计这些数字在最坏的情况下会保持不变。
我确实看到性能计数器报告删除过程中页面拆分的增加。
删除时,ghost 记录是否必须移动到另一页?这与“唯一标识符”有关吗?
我们正在推出 RCSI,但现在,RCSI 已关闭。
它是可用性组中的主节点。我知道快照以某种方式在辅助节点上使用。如果这是相关的,我会感到惊讶。我打算深入研究这个(查看 dbcc 页面输出)以了解更多信息。希望有人看到过类似的东西。
这是破败:我在做一个选择查询。WHERE
andORDER BY
子句中的每一列都在一个非聚集索引中IX_MachineryId_DateRecorded
,或者作为键的一部分,或者作为INCLUDE
列。我正在选择所有列,因此将导致书签查找,但我只使用TOP (1)
,因此服务器肯定会告诉查找只需要在最后完成一次。
最重要的是,当我强制查询使用 index 时IX_MachineryId_DateRecorded
,它会在不到一秒的时间内运行。如果我让服务器决定使用哪个索引,它会选择IX_MachineryId
,并且最多需要一分钟。这真的向我表明我已经正确地建立了索引,而服务器只是做出了一个错误的决定。为什么?
CREATE TABLE [dbo].[MachineryReading] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Location] [sys].[geometry] NULL,
[Latitude] FLOAT (53) NOT NULL,
[Longitude] FLOAT (53) NOT NULL,
[Altitude] FLOAT (53) NULL,
[Odometer] INT NULL,
[Speed] FLOAT (53) NULL,
[BatteryLevel] INT NULL,
[PinFlags] BIGINT NOT NULL,
[DateRecorded] DATETIME NOT NULL,
[DateReceived] DATETIME NOT NULL,
[Satellites] INT NOT NULL,
[HDOP] FLOAT …
Run Code Online (Sandbox Code Playgroud) 考虑到非聚簇索引是基于聚簇索引的,非聚簇索引是否有必要列出聚簇索引中包含的任何列?
换句话说,如果 Products 表包含 ProductID 上的聚集索引,那么在创建非聚集索引时建议包含 ProductID 列时,是否有必要将其添加为列?
如果没有,是否有将列名添加到非聚集索引的情况?
我有一个如下表:
create table [Thing]
(
[Id] int constraint [PK_Thing_Id] primary key,
[Status] nvarchar(20),
[Timestamp] datetime2,
[Foo] nvarchar(100)
)
Run Code Online (Sandbox Code Playgroud)
Status
在和字段上使用非聚集、非覆盖索引Timestamp
:
create nonclustered index [IX_Status_Timestamp] on [Thing] ([Status], [Timestamp] desc)
Run Code Online (Sandbox Code Playgroud)
如果我查询这些行的“页面”,使用偏移/获取如下,
select * from [Thing]
where Status = 'Pending'
order by [Timestamp] desc
offset 2000 rows
fetch next 1000 rows only
Run Code Online (Sandbox Code Playgroud)
我知道该查询需要读取总共 3000 行才能找到我感兴趣的 1000 行。然后我希望它对这 1000 行中的每一行执行键查找以获取索引中未包含的字段。
但是,执行计划表明它正在对所有 3000 行进行键查找。我不明白为什么,当唯一的条件(按[状态]过滤和按[时间戳]排序)都在索引中时。
如果我用 cte 重新表述查询,如下所示,我或多或少会得到我期望第一个查询执行的操作:
with ids as
(
select Id from [Thing]
where Status = 'Pending'
order by [Timestamp] …
Run Code Online (Sandbox Code Playgroud) 这是一个奇怪的情况,但我希望有人有答案。
在一些性能故障排除期间,我们按照sp_BlitzIndex
. 第二天我们检查了它的使用情况,它显示0 次读取(0 次扫描/搜索,0 次单例查找),因此我们禁用了它。
就在下一分钟,我们收到了与我们在添加 INDEX 时首先尝试检查和解决的应用程序缓慢(性能问题)相同的投诉。
现在,我知道理论上,这听起来纯属巧合。INDEX 是可证明的,可衡量的,NOT USED。禁用它不应该导致查询性能下降。但它几乎TOO巧合。
所以我的问题很简单,就是这样:
是否有可能,一个未使用的索引(来自 DMV / sp_BlitzIndex
)的使用统计数据显示没有使用,仍然以某种方式帮助受影响表上的查询性能?
database-design sql-server index-tuning nonclustered-index sql-server-2016
我将创建一个包含两个字段的表 - ID
asBIGINT
和IPAddress
asvarchar(45)
或者varbinary(16)
。这个想法是存储所有唯一的 IP 地址并使用引用ID
而不是IP address
其他表中的实际地址。
通常,我将创建一个存储过程,该过程返回ID
给定的IP address
或(如果未找到地址)插入地址并返回生成的ID
.
我期望有很多记录(我无法确切说出有多少),但我需要尽快执行上面的存储过程。所以,我想知道如何以文本或字节格式存储实际的 IP 地址。哪个会更好?
我已经编写了SQL CLR
用于将 IP 地址字节转换为字符串和反向转换的函数,因此转换不是问题(同时使用IPv4
和IPv6
)。
我想我需要创建一个索引来优化搜索,但我不确定我应该将该IP address
字段包含在聚集索引中,还是创建一个单独的索引以及使用哪种类型的搜索会更快?
database-design sql-server sql-server-2012 sql-clr nonclustered-index
实体关系图中的索引是什么样的?
我用谷歌搜索过,但不确定 ERD 中索引的标准外观是什么。我说的是包含所有字段的 crowsfoot 图。
我有一个超过 30 亿行的 SQL Server 表。我的一个查询需要很长时间,所以我正在考虑优化它。查询如下所示:
SELECT [Enroll_Date]
,Count(*) AS [Record #]
,Count(Distinct UserID) AS [User #]
FROM UserTable
GROUP BY [Enroll_Date]
Run Code Online (Sandbox Code Playgroud)
[Enroll_Date] 是具有少于 50 个可能值的低选择性列,而 UserID 列是具有超过 2 亿个不同值的高选择性列。根据我的研究,我认为我应该在这两列上创建一个非聚集复合索引,理论上高选择性列应该是第一列。但我不确定在我的情况下,这是否有效,因为我在 group by 子句中使用了低选择性列。
该表没有聚集索引。
给出下一个例子:
IF OBJECT_ID('dbo.my_table') IS NOT NULL
DROP TABLE [dbo].[my_table];
GO
CREATE TABLE [dbo].[my_table]
(
[id] int IDENTITY (1,1) NOT NULL PRIMARY KEY,
[foo] int NULL,
[bar] int NULL,
[nki] int NOT NULL
);
GO
/* Insert some random data */
INSERT INTO [dbo].[my_table] (foo, bar, nki)
SELECT TOP (100000)
ABS(CHECKSUM(NewId())) % 14,
ABS(CHECKSUM(NewId())) % 20,
n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
FROM
sys.all_objects AS s1
CROSS JOIN
sys.all_objects AS s2
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_my_table]
ON [dbo].[my_table] …
Run Code Online (Sandbox Code Playgroud) 我有一个开发人员希望在执行没有 order by 的 select 语句时,表中的行按照它们插入的顺序排列。开发人员建议从聚集索引更改为非聚集索引。
通过将索引从聚簇更改为非聚簇,这是否可以保证行在表中出现的顺序?
这个问题主要是为了我的好奇心;我将建议改用身份列,但这个请求让我开始思考。可以使用时间戳,但有可能同时插入行。
在此先感谢您的帮助。