【发布时间】:2019-07-03 19:58:03
【问题描述】:
我有一个看起来像这样的表:
CREATE TABLE Records
(
ID UNIQUEIDENTIFIER PRIMARY KEY NONCLUSTERED,
owner UNIQUEIDENTIFIER,
value FLOAT,
timestamp DATETIME
)
与此问题无关的其他一些列上存在多列聚集索引。
该表目前大约有 500,000,000 行,我需要对表进行操作,但目前太大而无法处理(我受到慢硬件的阻碍)。所以我决定分块进行。
如果我说
SELECT ID
FROM records
WHERE ID LIKE '0000%'
执行计划显示扫描了整个表。我认为使用索引,只有那些与原始条件匹配的行才会被扫描,直到 SQL 到达“0001”记录。有了前面的 %,我可以清楚地看到为什么它会扫描整个表。但是最后有 % ,它不应该扫描整个表。
我猜这与 GUID 而不是 CHAR 或 VARCHAR 列的工作方式不同。
所以我的问题是:如何在不必扫描整个表的情况下搜索 GUID 的一个小节?
【问题讨论】:
-
如果可能的话,您可以通过添加一个将 id 转换为 char 的 char 列并为此列创建和索引来进行测试,然后检查查询
-
GUID 不是字符串,而是 GUID are not stored as they are printed 的字节。此查询需要转换所有单独的行,这当然效率不高。 应该可以通过构建适当的表单并使用
>=和<进行比较(我认为LIKE模式不起作用)来分块GUID 处理,但这并不完全是微不足道的。你可以试试ROW_NUMBER()上的分块是否足够快;它肯定会简单得多。 -
@jeroen Mostert。这很有趣。因为我如何分块并不重要,我就是这么做的。如果 从左到右影响第 5 组,我可以轻松地动态构建边界。我会测试一下。
-
对于任何有订单(和
UNIQUEIDENTIFIER)的东西肯定会起作用的一件事就是要求TOP(x) ORDER BY ...,跟踪最后一行你看到了,然后用WHERE ... > lastvalue发出下一个。这样一来,SQL Server 如何对 GUID 进行排序并不重要,只要您跟踪您离开的位置即可。 -
话虽如此,除非您的列由
NEWSEQUENTIALID()填充(即使那样,因为它不是完全单调递增)添加新行将导致您的枚举中断并跳过行,这与@ 不同987654334@,这只是在正常情况下增加,即使它跳过值也是如此。所以请注意任何插入!
标签: sql-server sql-server-2012