SQL order by 分两步

Posted

技术标签:

【中文标题】SQL order by 分两步【英文标题】:SQL order by in two steps 【发布时间】:2020-12-31 11:04:02 【问题描述】:

我有一个有两个日期时间列的大表。

[Timestamp][TimestampRounded]

[Timestamp] 列具有完整的时间戳(包括毫秒),并且该表没有该列的索引。

[TimestampRounded] 列具有时间戳,但毫秒、秒和分钟被截断(设置为 0)。该表具有该列的聚集索引。即,表格有效地按此列的顺序存储。通常,最新的行位于表格的顶部。索引是这样创建的:

CREATE CLUSTERED INDEX cidx_time ON [dbo].[MyTable] ([TimestampRounded] DESC)

现在,我想利用我的聚集索引检索一些数据,所以我执行以下选择,我的表有大约 500 万行。

查询 1:

SELECT TOP(100) * FROM [dbo].[MyTable] ORDER BY [TimestampRounded] DESC

此查询立即返回(不到 1 秒)。但是返回的 100 行没有按毫秒排序,只是按小时排序。

然后我知道我是否也想按第二列排序:

查询 2:

SELECT TOP(100) * FROM [dbo].[MyTable] ORDER BY [TimestampRounded] DESC, [Timestamp] DESC

这个查询非常慢,大约需要 23 秒才能返回 100 行。

我的直接解决方案是使用第一个查询,然后在我的客户端前端代码中对返回的 100 行进行排序。但是我遇到了一些问题,我错过了应该返回的行,所以我想了解如何修复/重写查询 2 以按预期返回这 100 个排序的行,并且通过合理的逻辑也应该花费不到 1 秒。由于该表已经按小时存储(聚集索引),我不明白为什么需要更长的时间。

【问题讨论】:

TimestampRounded 有多少行在相同的最高值上? 可以将数千行绑定到 TimestampRounded 值。那就是在那一小时内发生的每一行 完全正确 - 所以您的第一个查询是“给我 any 100 行共享相同小时值的行” - 而您的第二个查询是“给我准确的 100 行最新的” - 第二个需要更多时间。 那么获得正确数据的合理性是什么?对聚集索引使用 [Timestamp]?据我所知,这不是最优的,因为索引将是不合理的,特别是由于时间戳中的毫秒和秒 我用这个问题的答案作为参考:***.com/questions/17381875/… 【参考方案1】:

我可能过于简单化了,但为什么不简单地在存储整个时间戳的列上创建一个索引呢?

CREATE INDEX cidx_time2 ON [dbo].[MyTable] ([Timestamp] DESC)

然后,你可以这样做:

SELECT TOP(100) * FROM [dbo].[MyTable] ORDER BY [[Timestamp] DESC

或者,如果您出于某种原因需要在 order by 子句中设置两个时间戳,那么您需要在两列上都有一个索引:

CREATE INDEX cidx_time3 ON [dbo].[MyTable] ([TimestampRounded] DESC, [Timestamp] DESC);

然后您可以运行原始查询:

SELECT TOP(100) * FROM [dbo].[MyTable] ORDER BY [TimestampRounded] DESC, [Timestamp] DESC

【讨论】:

我了解到,如果我的聚集索引包含毫秒、秒和分钟,那么 INSERT 会非常乏味。这就是为什么我首先使用圆角列 查看这个问题的答案:***.com/questions/17381875/… 不,那是错误的。无论哪种方式,它都是一个 64 位的值进行排序,它将具有相同的性能。当然,添加 another 列会让它变得更好 怎么了?你是说我应该删除 Rounded 列并在 [Timestamp] 上使用聚集索引? @Smith5727 最好忽略您链接的已接受答案 - 短语 the index has to account for every place within the datetime. This becomes very large spatially and bulky. 向我表明作者可能不知道索引是如何工作的【参考方案2】:

指定WITH TIES,这样 sqlserver 将返回[最多]“几千”行,这些行具有所有相同的舍入时间戳值,然后按精确时间戳对这几千行排序,以获得真正最新的 100;比数百万排序更快

【讨论】:

以上是关于SQL order by 分两步的主要内容,如果未能解决你的问题,请参考以下文章

sql中group by和order by的区别

sql 排序,order by 按时间

sql语句执行顺序之group by、order by

SQL中,group by 跟order by有什么区别?

SQL注入 order by后的注入(Less-46)

sql [mysql:ORDER BY中的CASE]在mysql的ORDER BY中使用CASE。 #mysql #sql