PostgreSQL - max number of parameters in “IN” clause?

后端 未结 8 1262
無奈伤痛
無奈伤痛 2020-11-28 21:58

In Postgres, you can specify an IN clause, like this:

SELECT * FROM user WHERE id IN (1000, 1001, 1002)

Does anyone know what\'s the maximu

相关标签:
8条回答
  • 2020-11-28 22:38
    explain select * from test where id in (values (1), (2));
    

    QUERY PLAN

     Seq Scan on test  (cost=0.00..1.38 rows=2 width=208)
       Filter: (id = ANY ('{1,2}'::bigint[]))
    

    But if try 2nd query:

    explain select * from test where id = any (values (1), (2));
    

    QUERY PLAN

    Hash Semi Join  (cost=0.05..1.45 rows=2 width=208)
           Hash Cond: (test.id = "*VALUES*".column1)
           ->  Seq Scan on test  (cost=0.00..1.30 rows=30 width=208)
           ->  Hash  (cost=0.03..0.03 rows=2 width=4)
                 ->  Values Scan on "*VALUES*"  (cost=0.00..0.03 rows=2 width=4)
    

    We can see that postgres build temp table and join with it

    0 讨论(0)
  • 2020-11-28 22:49

    As someone more experienced with Oracle DB, I was concerned about this limit too. I carried out a performance test for a query with ~10'000 parameters in an IN-list, fetching prime numbers up to 100'000 from a table with the first 100'000 integers by actually listing all the prime numbers as query parameters.

    My results indicate that you need not worry about overloading the query plan optimizer or getting plans without index usage, since it will transform the query to use = ANY({...}::integer[]) where it can leverage indices as expected:

    -- prepare statement, runs instantaneous:
    PREPARE hugeplan (integer, integer, integer, ...) AS
    SELECT *
    FROM primes
    WHERE n IN ($1, $2, $3, ..., $9592);
    
    -- fetch the prime numbers:
    EXECUTE hugeplan(2, 3, 5, ..., 99991);
    
    -- EXPLAIN ANALYZE output for the EXECUTE:
    "Index Scan using n_idx on primes  (cost=0.42..9750.77 rows=9592 width=5) (actual time=0.024..15.268 rows=9592 loops=1)"
    "  Index Cond: (n = ANY ('{2,3,5,7, (...)"
    "Execution time: 16.063 ms"
    
    -- setup, should you care:
    CREATE TABLE public.primes
    (
      n integer NOT NULL,
      prime boolean,
      CONSTRAINT n_idx PRIMARY KEY (n)
    )
    WITH (
      OIDS=FALSE
    );
    ALTER TABLE public.primes
      OWNER TO postgres;
    
    INSERT INTO public.primes
    SELECT generate_series(1,100000);
    

    However, this (rather old) thread on the pgsql-hackers mailing list indicates that there is still a non-negligible cost in planning such queries, so take my word with a grain of salt.

    0 讨论(0)
提交回复
热议问题