Postgresql – Indexes and windowing functions

indexindex-tuningpostgresql

We have a design in which a table stores the history of changes to an entity, and a view queries the table for the latest row for that entity.

Say, employee_history and employee (the view with latest status).

The view is defined using a rank() function:

create view employee as (
  select * from (
    select
      *
      , rank() over (partition by employee_id order by last_update_ts desc)
    from employee_history
  ) e
  where r = 1
)

There is an index over the employee_id and the update timestamp, both fields used in the view definition.
Most of the queries over this view are for a specific employee, with its ID. So the query engine makes good use of the index.

But now we need a query to find employees in some department, using the department name. This view definition cannot make use of the index.

How may I get a more performant query over the history table? I can create new indices and new views. I cannot create a new table containing only the current data; it has to be over the history table.

This is on Postgres 11.

Best Answer

Your query for a specific department can make use of the index:

create index on employee_history (employee_id , last_update_ts desc);

The index without the desc indeed cannot be used. I don't think there is a good reason for this, it is just some kind of oversight in the planner. However, this index usage of the index that can be used is not going to be particularly fast anyway. It will have to read the entire index and table. It will just avoid the sort of the entire table, not the reading of it.

This is a fundamental limitation of your questionable design. Without some extra limitations (like employees can never move between departments) I don't see anything you can do about this in general.