SQL Server:查找丢失 ID 的有效方法

Hau*_*aus 1 t-sql sql-server

我正在使用 SQL Server 来存储数千万条记录。我需要能够查询其表以查找 Id 列中存在间隙的缺失行,因为应该没有间隙。

我目前正在使用我在 StackOverflow 上找到的解决方案:

CREATE PROCEDURE [dbo].[find_missing_ids]
    @Table NVARCHAR(128)
AS
BEGIN
    DECLARE @query NVARCHAR(MAX)
    SET @query = 'WITH Missing (missnum, maxid) '
+ N'AS '
+ N'('
+ N' SELECT 1 AS missnum, (select max(Id) from ' + @Table + ') '
+ N'    UNION ALL '
+ N'    SELECT missnum + 1, maxid FROM Missing '
+ N'    WHERE missnum < maxid '
+ N') '
+ N'SELECT missnum '
+ N'FROM Missing '
+ N'LEFT OUTER JOIN ' + @Table + ' tt on tt.Id = Missing.missnum '
+ N'WHERE tt.Id is NULL '
+ N'OPTION (MAXRECURSION 0);';

    EXEC sp_executesql @query
END;
Run Code Online (Sandbox Code Playgroud)

该解决方案一直运行良好,但随着表的增长,它变得越来越慢并且占用更多资源。现在,在包含 3800 万行的表上运行该过程大约需要 3.5 分钟并占用大量 CPU。

有没有更有效的方法来执行此操作?在发现某个范围不包含任何缺失的 Id 后,我不再需要再次检查该范围。

Dav*_*ois 6

JBJ的回答已经差不多完成了。查询需要返回每个缺失值范围的 From 和 Through。

select B+1 as [From],A-1 as[Through]from
(select StuffID as A, 
lag(StuffID)over(order by StuffID)as B from Stuff)z
where A<>B+1
order by A
Run Code Online (Sandbox Code Playgroud)

我创建了一个包含 5000 万条记录的测试表,然后删除了一些记录。结果的第一行是:

From   Through
33     35
Run Code Online (Sandbox Code Playgroud)

这表明 33 到 35 范围内的所有 ID 均丢失,即 33、34 和 35。

在我的机器上,查询花了 37 秒。