Tenho uma tabela com dois índices:
- last_channel_snapshots_views_idx (view_count DESC NULLS LAST)
- last_channel_snapshots_network_views_idx (network_id, view_count DESC NULLS LAST)
O que eu quero é poder classificar por view_count geral e dentro de uma rede específica. O Postgres usa o índice correto para ambos os casos. No entanto, se eu quiser encontrar o registro com a maioria das visualizações em que network_id é NULL, ele usa o primeiro índice e filtra o , executando assim muito lento:
explain analyze SELECT *
FROM latest_channel_snapshots
WHERE network_id IS NULL
ORDER BY view_count DESC NULLS LAST
LIMIT 5 OFFSET 500000;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=39599.04..39599.44 rows=5 width=74) (actual time=1926.271..1926.287 rows=5 loops=1)
-> Index Scan using latest_channel_snapshots_views_idx on latest_channel_snapshots (cost=0.00..42001.59 rows=530336 width=74) (actual time=0.060..1899.224 rows=500005 loops=1)
Filter: (network_id IS NULL)
Rows Removed by Filter: 305022
Total runtime: 1926.309 ms
(5 rows)
Você tem dois problemas aqui:
deslocamento grande: o PG precisará varrer o número de linhas de deslocamento fornecido e preferirá um índice para fazer isso acima de uma varredura de tabela.
como indexar os dados: acho que um índice parcial pode ajudá-lo aqui. Você pode tentar
crie o índice xxx_idx em current_channel_snapshots (view_count DESC NULLS LAST) onde network_id é nulo;
Consulte http://www.postgresql.org/docs/9.2/static/indexes-partial.html para obter mais informações sobre índices parciais. Em particular, o exemplo 11-2 sobre pedidos não faturados parece se aplicar ao seu caso.