2

I have a very massive PostgreSQL database table. One of its columns stores a boolean parameter. What I want is a very simple query:

SELECT COUNT(*) FROM myTable WHERE myTable.isSthTrue;

The problem I have is that it is very slow as it needs to check every row if it satisfies the criteria. Adding an index to this parameter speeds up the calculation roughly two times, but doesn't really improve the complexity in general.

Some people on the internet suggest adding triggers that update the count which is stored in a separate table. But that feels like too much effort for an easy problem like this.

5
  • 1
    How many rows do you have in that table? And how many rows qualify for that condition? And what index did you add exactly? What is the output of explain (analyze, verbose) for the query with and without the index? And what is the current performance? And how fast do you need it to be? Also which version are you using? Commented Nov 23, 2015 at 22:10
  • Did you try adding a partial index on isSthTrue WHERE isSthTrue is true ? Commented Nov 23, 2015 at 22:13
  • @a_horse_with_no_name Currently I have 100k, but in real system there are going to be around 10M. Number of rows that qualify for the condition might be anything between 1-75%. I added btree index. explain analyze says that it is using seq scan without index and Index only scan with index, as expected. Performance is in hundreds of milis. So I don't want it to take dozens of seconds in real system to do such a simple query. I am using 9.3.sth version. Commented Nov 24, 2015 at 15:10
  • @ConsiderMe It doesn't look like it would do anything Commented Nov 24, 2015 at 15:10
  • @eddyP a partial index only builds up btree of values that meet where condition. I'm sure that the size of an index would be much less than the whole, non-partial one. Commented Nov 24, 2015 at 22:25

1 Answer 1

1

If you need an exact result.

Then, yes, a trigger-based solution is likely the best path to go.

If an estimate is okay, consider Materialized Views. (Postgres 9.3+)

Something like CREATE MATERIALIZED VIEW myCount AS SELECT COUNT(*) FROM myTable WHERE myTable.isSthTrue; would maintain a copy of the expensive query you reference. The only caveat is that this aggregate view would not be automatically updated. To do that you need to call REFRESH MATERIALIZED VIEW, which could be done in a cron, or other timed task.

Sign up to request clarification or add additional context in comments.

1 Comment

As at August 2018, the link "check out this resource" is spam.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.