无法修复的空间索引损坏是否正常?

boo*_*ife 23 sql-server spatial dbcc-checkdb sql-server-2014

我有一个空间索引用于该DBCC CHECKDB报告损坏:

DBCC CHECKDB(MyDB) 
WITH EXTENDED_LOGICAL_CHECKS, DATA_PURITY, NO_INFOMSGS, ALL_ERRORMSGS, TABLERESULTS
Run Code Online (Sandbox Code Playgroud)

空间索引、XML 索引或索引视图“sys.extended_index_xxx_384000”(对象 ID xxx)不包含视图定义生成的所有行。这不一定表示此数据库中的数据存在完整性问题。

空间索引、XML 索引或索引视图“sys.extended_index_xxx_384000”(对象 ID xxx)包含不是由视图定义生成的行。这不一定表示此数据库中的数据存在完整性问题。

CHECKDB 在表“sys.extended_index_xxx_384000”(对象 ID xxx)中发现 0 个分配错误和 2 个一致性错误。

维修级别为repair_rebuild.

删除并重新创建索引不会删除这些损坏报告。没有EXTENDED_LOGICAL_CHECKS但有DATA_PURITY错误是不报告的。

此外,CHECKTABLE尽管它的 CI 大小为 30 MB 并且有大约 30k 行,但该表需要 45 分钟。该表中的所有数据都是点geography数据。

在任何情况下都会出现这种行为吗?它说“这不一定代表完整性问题”。我应该做些什么?CHECKDB正在失败这是一个问题。

此脚本重现了该问题:

CREATE TABLE dbo.Cities(
    ID int  NOT NULL,
    Position geography NULL,
 CONSTRAINT PK_Cities PRIMARY KEY CLUSTERED 
(
    ID ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

GO
INSERT dbo.Cities (ID, Position) VALUES (20171, 0xE6100000010C4E2B85402E424A40A07312A518C72A40)
GO
CREATE SPATIAL INDEX IX_Cities_Position ON dbo.Cities
(
    Position
)USING  GEOGRAPHY_AUTO_GRID 
WITH (
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

这是版本 12.0.4427.24 (SQL Server 2014 SP1 CU3)。

我用模式和数据、新的数据库、执行为表编写了脚本。同样的错误。CHECKDB 还拥有令人难以置信的 45 分钟运行时间。我使用 SQL Profiler 捕获了 CHECKDB 查询计划。它有一个错误的循环连接,显然会导致运行时间过长。该计划在表的行数中具有二次运行时间!双嵌套扫描循环连接。

DBCC 执行计划

清除所有非空间索引不会改变任何东西。

Mar*_*ith 25

我无法立即在 2014 年 - 12.0.4213.0 上重现此内容,但在 SQL Server 2016 (CTP3.0) - 13.0.700.242 上确实可以看到它。

在 2014 构建(没有 DBCC 错误)上,计划如下所示。

在此处输入图片说明

在 2016 年的构建中(报告DBCC 错误),就像这样。

在此处输入图片说明

第二个计划有一行来自合并反半连接,第一个计划零行。

连接谓词pk0在与空间索引中的列匹配的内容方面有所不同。

在此处输入图片说明

第一个正确地将它映射到表主键,第二个将它映射到Id从 TVF 返回的列。

根据 SQL Server 2012 internals book,这是单元格的希尔伯特数的 binary(5) 值,因此该谓词肯定是不正确的(如果基表中单行的 Id 设置为 1052031049 而不是 20171 我不不再看到任何 DBCC 错误,因为这恰好对应于 ) 的这个值0xa03eb4b849


在 2014 年 - 12.0.4213.0 重新创建表如下后,我可以重现该问题。

CREATE TABLE dbo.Cities(
    Id int  NOT NULL,
    Position geography NULL,
 CONSTRAINT PK_Cities PRIMARY KEY CLUSTERED 
(
    Id ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
Run Code Online (Sandbox Code Playgroud)

(注意从ID到的变化Id

我的 2014 实例安装了区分大小写的排序规则。所以看起来这可能已经防止了之前的列混淆。

所以我想一个潜在的解决方法可能是将列重命名CitiesCityId例如。

连接项(Microsoft 错误报告)

  • @boot4life `Id` 混淆也会导致应该寻找扫描。伟大的捕获,马丁。它似乎只影响“AUTO_GRID”选项。我可以使用不区分大小写的排序规则重现 2014 SP1 CU4 上的错误。SQL Server 错误地构建了扩展检查查询。 (7认同)
  • 这是一个很棒的错误 :) 也可以解释疯狂的循环连接,因为它们可能只是这种可能更高基数的连接条件的不错选择。 (4认同)