Sql server 对guid使用LIKE-in-WHERE子句会导致全表扫描

Sql server 对guid使用LIKE-in-WHERE子句会导致全表扫描,sql-server,sql-server-2012,Sql Server,Sql Server 2012,我有一张像这样的桌子: CREATE TABLE Records ( ID UNIQUEIDENTIFIER PRIMARY KEY NONCLUSTERED, owner UNIQUEIDENTIFIER, value FLOAT, timestamp DATETIME ) 在与此问题无关的其他一些列上存在多列聚集索引 该表目前有大约500000000行,我需要在该表上操作,但它太大,目前无法处理(我受到缓慢硬件的阻碍)。所以我决定分块做 但如果我说 SEL

我有一张像这样的桌子:

CREATE TABLE Records 
(
    ID UNIQUEIDENTIFIER PRIMARY KEY NONCLUSTERED,
    owner UNIQUEIDENTIFIER,
    value FLOAT,
    timestamp DATETIME
)
在与此问题无关的其他一些列上存在多列聚集索引

该表目前有大约500000000行,我需要在该表上操作,但它太大,目前无法处理(我受到缓慢硬件的阻碍)。所以我决定分块做

但如果我说

SELECT ID 
FROM records
WHERE ID LIKE '0000%'
执行计划显示扫描了整个表。我认为使用索引,只有那些与原始条件匹配的行才会被扫描,直到SQL到达“0001”记录。在前面有%的情况下,我可以清楚地看到为什么它会扫描整个表。但由于%位于末尾,它不必扫描整个表

我猜这与guid不同,而不是
CHAR
VARCHAR


因此,我的问题是:如何在不扫描整个表的情况下搜索GUID的一部分?

从您的评论中,我看到实际需要的是根据范围将随机GUID值的行分成块(有序)。在这种情况下,您可以指定一个范围,而不是像那样指定最后一组中所需的开始/结束值的过滤器:

SELECT ID
FROM dbo.records
WHERE
    ID BETWEEN '00000000-0000-0000-0000-000000000000'
    AND '00000000-0000-0000-0000-000FFFFFFFFF';

解释如何在SQL Server中存储和排序UniqueIdentifier(GUID),首先比较和排序最后一个组,而不是按预期从左到右排序。通过对最后一个组进行筛选,您将获得一个可搜索表达式,并仅接触指定范围内的行(假设使用了
ID
上的索引)。

如果可能,您可以通过添加一个ID已转换为char的char列并为此列创建和索引来测试这一点,然后检查queryA GUID是否为字符串,和GUID的字节数。这个查询需要对所有单独的行进行转换,这当然不是很有效。通过构造适当的表单并使用
=
@jeroen-Mostert,应该可以将GUID处理分块。这很有趣。因为不管我怎么拼,我都会。如果<和>影响从左到右的第五组,我可以很容易地动态构建边界。我将对此进行测试。对于任何有订单(并且
UNIQUEIDENTIFIER
有订单)的情况,一件肯定有效的事情就是在…
之前请求
顶部(x)订单,跟踪您看到的最后一行,并在下一行中发出
WHERE…>lastvalue
。这样一来,SQL Server如何对GUID进行排序并不重要,只要您跟踪停止的位置即可。尽管如此,除非您的列由
NEWSEQUENTIALID()
填充(即使如此,因为它不是完全单调递增的),否则添加新行将导致枚举中断并跳过行,不同于
标识
,该标识在正常情况下即使跳过值也只会增加。所以要注意任何插入!这是可行的,但要考虑字节顺序。我可以将表分成4096个大致相等的块,如下所示:从ID介于“00000000-0000-0000-0000-000000000000”和“00000000-0000-0000-0000-000FFFFFFF”之间的记录中选择ID,然后更改第5字节组开头的000的值。如果你想稍微修改你的答案,我会把它标记为关闭。谢谢。您可能值得阅读这篇关于guid如何在不同的上下文中进行不同排序的文章:@RobertSievers,我参考了这个链接和您的特定用例改进了我的答案。下面详细介绍了SQL Server的字节交换顺序,以便为SQL Server生成顺序GUID。