代码之家  ›  专栏  ›  技术社区  ›  Simon Perepelitsa

Postgres不在整数数组上使用索引

  •  0
  • Simon Perepelitsa  · 技术社区  · 4 年前

    我可以创建一个索引来加速数组操作。

    create table test_array as
      select id, array[id, id+1, id+2]::text[] as codes
      from generate_series(1, 10000) as id;
    
    create index test_array_idx on test_array using GIN (codes);
    
    explain analyze
    select * from test_array where codes @> array['123'];
    -- Uses "Bitmap Index Scan on test_array_idx"
    

    但是,索引不能用于整数数组。

    create table test_intarray as
      select id, array[id, id+1, id+2] as codes
      from generate_series(1, 10000) as id;
    
    create index test_intarray_idx on test_intarray using GIN (codes);
    
    explain analyze
    select * from test_intarray where codes @> array[123];
    -- Uses "Seq Scan on test_intarray"
    

    为什么会这样?

    1 回复  |  直到 4 年前
        1
  •  4
  •   Simon Perepelitsa    4 年前

    如果安装了“ intarray “延伸。让我们来测试一下:

    drop extension intarray;
    
    explain analyze
    select * from test_intarray where codes @> array[123];
    -- Uses "Bitmap Index Scan on test_intarray_idx"
    

    @> ,而索引是为使用泛型数组运算符而设计的。这可以通过使用模式限定运算符来证明:

    create extension intarray;
    
    explain analyze
    select * from test_intarray where codes @> array[123];
    -- Uses "Seq Scan on test_intarray"
    
    explain analyze
    select * from test_intarray where codes operator(pg_catalog.@>) array[123];
    -- Uses "Bitmap Index Scan on test_intarray_idx"
    

    有关详细信息,请参阅此讨论: Overloaded && operator from intarray module prevents index usage.

    如果您还想利用“intarray”扩展,可以在创建索引时指定它自己的运算符类“gin_uint_ops”(而不是默认的“array_ops”):

    create index test_intarray_idx2 on test_intarray using GIN (codes gin__int_ops);
    
    explain analyze
    select * from test_intarray where codes @> array[123];
    -- Uses "Bitmap Index Scan on test_intarray_idx2"