it's a third-party vendor application, not easy to change their code.
is it possible to   1) in Postgresql JDBC driver connection, set
plan_cache_mode=force_custom_plan
  or 2) some other parameters can workaround this issue?

Thanks,

James

Laurenz Albe <laurenz.a...@cybertec.at> 於 2024年2月23日週五 下午5:17寫道:

> On Fri, 2024-02-23 at 15:20 +0800, James Pang wrote:
> >    we have a SQL from Postgresql JDBC,  primary is based on
> (bigint,varchar2,bigint),
> > but from sql plan, it convert to ::numeric so the plan just use one
> "varchar"
> > key column and use the other 2 bigint keys as filters. what's the cause
> about that ?
> >
> >                             Table "test.xxxxxx"
> >       Column      |              Type              | Collation |
> Nullable | Default
> >
> ------------------+--------------------------------+-----------+----------+---------
> >   xxxid           | bigint                         |           | not
> null |
> >  paramname        | character varying(512)         |           | not
> null |
> >  paramvalue       | character varying(1536)        |           |
>  |
> >   sssid           | bigint                         |           | not
> null |
> >  createtime       | timestamp(0) without time zone |           |
>  |
> >  lastmodifiedtime | timestamp(0) without time zone |           |
>  |
> >  mmmuuid          | character varying(32)          |           |
>  |
> > Indexes:
> >       "pk_xxxxxx" PRIMARY KEY, btree (xxxid, paramname, sssid)
> >       "idx_xxxxxx_mmmuuid" btree (sssid, mmmuuid, paramname)
> >
> > SET extra_float_digits = 3
> >
> > duration: 7086.014 ms  plan:
> >         Query Text: SELECT XXXFID, PARAMNAME, PARAMVALUE, SSSID,
> CREATETIME, LASTMODIFIEDTIME, MMMUUID FROM test.XXXXXX WHERE  ( ( XXXID =
> $1  ) )  AND  ( ( PARAMNAME = $2  ) )  AND  ( ( SSSID = $3  ) )
> >         Index Scan using pk_xxxxxx on test.xxxxxx
>  (cost=0.57..2065259.09 rows=1 width=86) (actual time=7086.010..7086.011
> rows=0 loops=1)
> >           Output: confid, paramname, paramvalue, sssid, createtime,
> lastmodifiedtime, mmmuuid
> >           Index Cond: ((xxxxxx.paramname)::text = 'cdkkifffff'::text)
>  <<< just use only one key instead all primary keys.
> >           Filter: (((xxxxxx.xxxid)::numeric = '18174044'::numeric) AND
> ((xxxxxx.sssid)::numeric = '253352'::numeric))    <<< it's bigint but
> converted to numeric
> >           Buffers: shared read=1063470
> >           I/O Timings: read=4402.029
> >
> > it's from JDBC, we saw this JDBC driver try to set extra_float_digits =
> 3 before
> > running the SQL ,does that make planner to convert bigint to numeric ?
>
> Setting "extra_float_digits" is just something the JDBC driver does so as
> to
> not lose precision with "real" and "double precision" values on old
> versions
> of PostgreSQL.
>
> The problem is that you bind the query parameters with the wrong data
> types.
> Don't use "setBigDecimal()", but "setLong()" if you want to bind a
> "bigint".
> An alternative is "setObject()" with "targetSqlType" set to "Types.BIGINT".
>
> Yours,
> Laurenz Albe
>

Reply via email to