O Postgres suporta funções de janela que se adequam a esta situação:
select date, symbol, value, created_time
from (select *,
rank() over (partition by date, symbol order by created_time desc) as rownum
from test_table) x
where rownum = 1
Para cada combinação de
date , symbol , esta consulta retorna o value e created_time da linha com o maior (ou seja, último ) created_time dessa date e symbol . Sugiro este índice:
CREATE UNIQUE INDEX test_table_idx
ON test_table (date, symbol, created_time, value)
É uma cobertura index (tem todos os valores que você precisa para a consulta, eliminando a necessidade de acessar a tabela real e que você já tinha), mas observe que
created_time vem antes value , então os dados já estão em sua ordem de partição e value é o atributo menos importante, pois não participa de nenhuma determinação de qual linha retornar.