使用 row_number() 选择第一行

Posted

技术标签:

【中文标题】使用 row_number() 选择第一行【英文标题】:Selecting first row using row_number() 【发布时间】:2017-06-19 15:46:39 【问题描述】:

我想知道 ROW_NUMBER() 的性能: 在我的测试用例中,我有许多元素,每个元素中都有大量(~100k)条目。我想为每个元素选择第一个条目:

SELECT * FROM(    
    SELECT 
      element, msg, timestamp, 
      ROW_NUMBER() OVER(PARTITION BY element ORDER BY timestamp) as rank
    FROM table
) t1
WHERE rank = 1

对我来说,为了保留第一个分区而需要为每个分区订购所有 100k 行似乎有些过分。像 MIN() 函数这样的东西应该天真地表现得更好。 所以我尝试了这样的事情:

SELECT
  element, MIN(a)[0] as timestamp, MIN(a)[1] as msg
FROM(
    SELECT element, ARRAY(timestamp, msg) as a
    FROM table
) t1
GROUP BY partition

但是当比较这两种方法的 CPU 使用率时,我得到了相同的性能。 ROW_NUMBER() 优化器比我想象的要聪明得多,还是我遗漏了什么?

编辑:我的原始查询中有一个错误。现在查看结果,似乎 MIN(ARRAY) 方法比 ROW_NUMBER() 过滤器快相当。有没有一种更简单的规范方法来实现 FIRST_ROW OVER(PARTITION) 过滤器,而不必定义一个庞大的数组然后解构它?

【问题讨论】:

也许使用交叉应用和按时间戳排序的seelect top 1? @xQbert 不是所有行都按时间戳排序,然后才应用前 1 个选择吗? No 不适用。它是一个表值函数,而不是一个连接,它在与元素相关时占据第一行。所以只会加入每个元素的前 1 个(最旧的)时间戳。 ***.com/questions/9275132/… sorry external apply not cross: ***.com/questions/9275132/… 【参考方案1】:

你错过了一些东西。 GROUP BY 需要做很多工作——看起来与ROW_NUMBER() 相似。

我对 Hive 的底层机制并不十分熟悉。在大多数数据库中,ROW_NUMBER() 将获取行的物理标识符、各种键,并分别对它们进行排序。使用物理标识符,然后可以将值快速添加回原始数据。当然,细节可能因数据库而异,但这是大体思路。

Hive 可能不会这样做。但是,无论它做什么,在努力方面都类似于GROUP BY

【讨论】:

以上是关于使用 row_number() 选择第一行的主要内容,如果未能解决你的问题,请参考以下文章

使用 ROW_NUMBER 函数选择最后一行

Redshift中的ROW_NUMBER()从每个组中选择最大的行?

如何在Postgresql的一行中获取第一个和最后一个值[关闭]

ROW_NUMBER() 替代

Access 选择语句中的 Row_Number()

SQL Server中row_number函数用法介绍