DISTINCT ON 对于 300000 行来说很慢

Meh*_*diB 2 sql postgresql greatest-n-per-group distinct-on postgresql-performance

我有一个名为资产的表。这是 ddl:

create table assets (
    id            bigint                                 primary key,
    name          varchar(255)                           not null,
    value         double precision                       not null,
    business_time timestamp with time zone,
    insert_time   timestamp with time zone default now() not null
);

create index idx_assets_name on assets (name);
Run Code Online (Sandbox Code Playgroud)

我需要为每个资产名称提取最新的(基于 insert_time)值。这是我最初使用的查询:

SELECT DISTINCT
    ON (a.name) *
FROM home.assets a
WHERE a.name IN (
                 'USD_RLS',
                 'EUR_RLS',
                 'SEKKEH_RLS',
                 'NIM_SEKKEH_RLS',
                 'ROB_SEKKEH_RLS',
                 'BAHAR_RLS',
                 'GOLD_18_RLS',
                 'GOLD_OUNCE_USD',
                 'SILVER_OUNCE_USD',
                 'PLATINUM_OUNCE_USD',
                 'GOLD_MESGHAL_RLS',
                 'GOLD_24_RLS',
                 'STOCK_IR',
                 'AED_RLS',
                 'GBP_RLS',
                 'CAD_RLS',
                 'CHF_RLS',
                 'TRY_RLS',
                 'AUD_RLS',
                 'JPY_RLS',
                 'CNY_RLS',
                 'RUB_RLS',
                 'BTC_USD'
    )
ORDER BY a.name,
         a.insert_time DESC;
Run Code Online (Sandbox Code Playgroud)

我的资产表中有大约 300,000 行。在我的 VPS 上,此查询大约需要 800 毫秒。这导致特定端点的整体响应时间约为 1 秒。这有点慢,考虑到资产表增长很快,这个端点在不久的将来会更慢。我还尝试避免IN(...)使用此查询:

SELECT DISTINCT
    ON (a.name) *
FROM home.assets a
ORDER BY a.name,
         a.insert_time DESC;
Run Code Online (Sandbox Code Playgroud)

但我没有注意到有什么显着差异。知道如何优化这个查询吗?

Tim*_*sen 6

您可以尝试将以下索引添加到表中:

CREATE INDEX idx ON assets (name, insert_time DESC);
Run Code Online (Sandbox Code Playgroud)

insert_time如果使用,Postgres 可以简单地扫描该索引来查找每个名称具有最新记录的不同记录。