SQL服务器模数运算符跳过大表上的每第n行

Bri*_*ian 5 sql sql-server sql-server-2012

我有一张100,000,000行的大桌子.我想从表中选择每一行.我的第一直觉是使用这样的东西:

SELECT id,name FROM table WHERE id%125000=0
Run Code Online (Sandbox Code Playgroud)

检索800行的均匀传播(id是聚簇索引)

这种技术在较小的数据集上运行良好,但对于我的较大的表,查询需要2.5分钟.我假设这是因为模数运算应用于每一行.是否有更优化的行跳过方法?

Gor*_*off 1

如果id在索引中,那么我正在考虑以下内容:

with ids as (
      select 1 as id
      union all
      select id + 125000
      from ids
      where id <= 100000000
  )
select ids.id,
       (select name from table t where t.id = ids.id) as name
from ids
option (MAXRECURSION 1000);
Run Code Online (Sandbox Code Playgroud)

我认为这个公式将使用表上的索引。

编辑:

当我考虑这种方法时,您实际上可以使用它来获取表中实际的随机 id,而不仅仅是均匀间隔的 id:

with ids as (
      select 1 as cnt,
             ABS(CONVERT(BIGINT,CONVERT(BINARY(8), NEWID()))) % 100000000 as id
      union all
      select cnt + 1, ABS(CONVERT(BIGINT,CONVERT(BINARY(8), NEWID()))) % 100000000
      from ids
      where cnt < 800
  )

select ids.id,
       (select name from table t where t.id = ids.id) as name
from ids
option (MAXRECURSION 1000);
Run Code Online (Sandbox Code Playgroud)

实际随机数生成器的代码来自这里

编辑:

由于 SQL Server 中的怪癖,即使在您的场景中,您仍然可以获得不连续的 id。这个接受的答案解释了原因。简而言之,身份值不是一次分配一个,而是成组分配。服务器可能会失败,甚至未使用的值也会被跳过。

我想要进行随机抽样的原因之一是为了帮助避免这个问题。据推测,上述情况在大多数系统上相当罕见。您可以使用随机采样来生成 900 个 id。从这些中,您应该能够找到 800 个实际上可用于您的样本的值。