0

We have a severe misprediction of cardinality of some columns on some tables in our system after running ANALYZE (the tables in question have hundreds of millions to billions records). Increasing statistics target to the max = 10000 helps only a little. It seems in our case we can't make it work with acceptable accuracy using regular Postgres mechanisms, because of our data distribution and probabilistic sampling of Postgres.
We could in theory collect n_distinct and mcv values ourselves, the overhead on that may be acceptable. The question is, would it be ok to update pg_statistic, pg_statistic_ext and pg_statistic_ext_data manually? Are there any known side effects of that?
P.S. I'm aware that we can set n_distinct on the columns through ALTER TABLE, but collection of mcv values will still be on Postgres.

9
  • You can try extended statistics with CREATE STATISTICS. But without seeing EXPLAIN (ANALYZE, BUFFERS) output for your actual query, I cannot say anything definitive. Commented Jan 9, 2023 at 6:57
  • @LaurenzAlbe Yeah, we have a bunch of extended statistics objects as well. It helped tangentially, but didn't solve the problem. Also, it's not just one query, it's across the board problem. The problem is our queries typically have 6-7 joins and depending on input the plans should be pretty different. The queries work mostly pretty well (for > 90% of input parameters, but for a small percentage we get very inefficient execution plans).
    – vladich
    Commented Jan 9, 2023 at 7:12
  • I see only 2 ways in this situation actually. Initially I thought it may be possible to collect more accurate statistics than postgres, hence the question above. Although I found that pg_statistic can't be updated because of anyarray data type for which updates are forbidden, so that's probably out of the question already. Another one is to basically implement our own planner, i.e. based on our own app-collected statistics force optimizer to choose this or that execution plan using pg_hint_plan and enabling/disabling optimizer features. This seems ugly, but it might work...
    – vladich
    Commented Jan 9, 2023 at 7:12
  • As I said, without seeing a typical example, it is hard to give advice. The problem could also be your data model. Commented Jan 9, 2023 at 7:17
  • @LaurenzAlbe That would be a long discussion not well suitable for stackoverflow. Assuming the problem is in insufficient accuracy of statistics that Postgres can generate (I have a good evidence of that, i.e. even for n_distinct calculated manually vs by ANALYZE I sometimes see an order of magnitude differences) . It's a well known issue for large datasets. What do you think could be realistic solutions? I'm asking in general, of course if we get into the details there could be something more suitable for our case. But I'm curious if there are any general ideas I'm not familiar with.
    – vladich
    Commented Jan 9, 2023 at 7:31

2 Answers 2

1

There is no way to override the statistics PostgreSQL collects, with the exception of n_distinct, which can be set with ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...). You can update pg_statistic if you are a superuser, but the data types used might require that you use a C function. Also, updating catalog tables is not supported and not a good solution here, because these statistics are lost during an upgrade or whenever autovacuum decides to ANALYZE the table.

1
  • If you effectively collect your own statistics, autoanalyze can be turned off, that shouldn't be an issue. Upgrade could be an issue, but that's an issue in any case... But yes, it seems it's not possible to update pg_statistic by conventional means...
    – vladich
    Commented Jan 9, 2023 at 8:11
1

Actually, I've found a way to do that (by looking at some abandoned extension of Postgres Pro - https://github.com/postgrespro/postgrespro/tree/DEV/contrib/dump_stat). The way to write into anyarray columns is to utilize some obscure function called array_in. It's very underdocumented, I'd say, only mentioned in Postgres documentation once, but it can do the trick.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.