Create a unique index on a non-unique column

痴心易碎 提交于 2019-11-29 23:50:39

问题


Not sure if this is possible in PostgreSQL 9.3+, but I'd like to create a unique index on a non-unique column. For a table like:

CREATE TABLE data (
  id SERIAL
  , day DATE
  , val NUMERIC
);
CREATE INDEX data_day_val_idx ON data (day, val); 

I'd like to be able to [quickly] query only the distinct days. I know I can use data_day_val_idx to help perform the distinct search, but it seems this adds extra overhead if the number of distinct values is substantially less than the number of rows in the index covers. In my case, about 1 in 30 days is distinct.

Is my only option to create a relational table to only track the unique entries? Thinking:

CREATE TABLE days (
  day DATE PRIMARY KEY
);

And update this with a trigger every time we insert into data.


回答1:


An index can only index actual rows, not aggregated rows. So, yes, as far as the desired index goes, creating a table with unique values like you mentioned is your only option. Enforce referential integrity with a foreign key constraint from data.day to days.day. This might also be best for performance, depending on the complete situation.

However, since this seems to be about performance, there is an alternative solution: you can use a recursive CTE to emulate a loose index scan:

WITH RECURSIVE cte AS (
   (SELECT day FROM data ORDER BY 1 LIMIT 1)
   UNION ALL
   SELECT (SELECT day FROM data WHERE day > c.day ORDER BY 1 LIMIT 1)
   FROM   cte  c
   )
SELECT day FROM cte;

This only needs a plain index on day.

There are various variants, depending on your actual queries. Details:

  • Optimize GROUP BY query to retrieve latest record per user
  • Unused index in range of dates query
  • Select first row in each GROUP BY group?


来源:https://stackoverflow.com/questions/29171623/create-a-unique-index-on-a-non-unique-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!