Jar*_*und 3 sql postgresql performance
所以,我有一个大约有150万行的表,看起来有点像这样:
name | time | data1 | data2
--------------------------------------
93-15 | 1337348782 | 11 | 60.791
92-02 | 1337348783 | 11 | 62.584
92-02 | 1337348056 | 11 | 63.281
93-15 | 1337348068 | 8 | 65.849
92-02 | 1337348117 | 11 | 63.271
93-15 | 1337348129 | 8 | 65.849
92-02 | 1337348176 | 10 | 63.258
93-15 | 1337348188 | 8 | 65.849
92-02 | 1337348238 | 10 | 63.245
93-15 | 1337348248 | 8 | 65.849
Run Code Online (Sandbox Code Playgroud)
...这些对应于需要监控的事物的历史状态更新.现在,我想做的是找到每个单位的当前状态.
在stackoverflow上找到类似的问题并不难,并从结果中推断,我想出了这个查询:
SELECT * FROM vehicles v
JOIN ( SELECT MAX(time) as max, name
FROM vehicles
GROUP BY name)
m_v
ON (v.time = m_v.max AND v.name = m_v.name);
Run Code Online (Sandbox Code Playgroud)
但是看到我有大约150万行(并且正在计数),是否有一种不同的方法可以加快查询速度?
WITH
sequenced_data
AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY name ORDER BY time DESC) AS sequence_id,
*
FROM
vehicles
)
SELECT
*
FROM
sequenced_data
WHERE
sequence_id = 1
Run Code Online (Sandbox Code Playgroud)
覆盖指数(name, time)也会有所帮助.
编辑:关于它是如何工作的注释等.
PostgreSQL具有窗口或分析功能.这些通常采取的形式some_function() OVER (PARTITION BY some_fields ORDER BY some_fields).
在这种情况下,我用过ROW_NUMBER() OVER (PARTITION BY name ORDER BY time DESC).
ROW_NUMBER()为一组数据创建唯一的行号. 1 to n为n记录.
PARTITION BY name表示此函数独立应用于不同的名称.每个name都是它自己的组/窗口/分区,以及每个组/窗口/分区的重新ROW_NUMBER()开始的结果1.
ORDER BY time DESC获取一个组/窗口/分区中的所有记录,并按照time字段对它们进行排序,在ROW_NUMBER()应用函数之前,首先使用最高值.
因此,对于您的示例数据,您可以获得此...
name | time | data1 | data2 | row_number
--------------------------------------------------
92-02 | 1337348783 | 11 | 62.584 | 1
92-02 | 1337348238 | 10 | 63.245 | 2
92-02 | 1337348176 | 10 | 63.258 | 3
92-02 | 1337348117 | 11 | 63.271 | 4
92-02 | 1337348056 | 11 | 63.281 | 5
93-15 | 1337348782 | 11 | 60.791 | 1
93-15 | 1337348248 | 8 | 65.849 | 2
93-15 | 1337348188 | 8 | 65.849 | 3
93-15 | 1337348129 | 8 | 65.849 | 4
93-15 | 1337348068 | 8 | 65.849 | 5
Run Code Online (Sandbox Code Playgroud)
因为排序是time DESC,价值最高的time领域,在每个name组/窗/分区,总会有一个row_number的1.
(name, time)通过确保数据处于友好的顺序,索引使优化器更容易.这意味着ROW_NUMBER()实际上并未应用于所有记录; 一旦找到最高价值的time记录并分配ROW_NUMBER() = 1,它就会知道它可以停止并继续下一个name.