PostgreSQL - 它会在同一个表上使用两个索引吗?

时间:2017-10-11 15:12:44

标签: postgresql indexing

假设您有一个包含某些索引的表:

create table mail
(
    identifier serial primary key,
    member text,
    read boolean
);

create index on mail(member_identifier);
create index on mail(read);

如果您现在查询具有单独索引的多个列,它是否会使用这两个索引?

select * from mail where member = 'Jess' and read = false;

也就是说,PostgreSQL可以决定首先使用member上的索引获取Jess的所有邮件,然后使用read上的索引获取所有未读邮件,然后将两个结果相交以构建输出集?

我知道你可以有一个包含多列的索引(在这种情况下在(member, read)上),但是如果你有两个单独的索引会发生什么? PostgreSQL会选择一个还是在某些情况下可以同时使用它们?

这不是关于特定查询的问题。理解内部结构是一个普遍的问题。

2 个答案:

答案 0 :(得分:5)

Postgres Documentation about multiple query indexes

文章说,它将创建两个索引适用的位置的抽象表示,然后结合结果。

  

要组合多个索引,系统会扫描每个所需的索引和   在内存中准备一个位图,给出表行的位置   报告为匹配该索引的条件。然后是位图   根据查询需要将ANDed和ORed组合在一起。最后,实际   访问并返回表行。

答案 1 :(得分:3)

CREATE TABLE fifteen
        (one serial PRIMARY KEY
        , three integer not NULL
        , five integer not NULL
        );

INSERT INTO fifteen(three,five)
SELECT gs%33+5,gs%55+11
FROM generate_series(1,60000) gs
        ;

CREATE INDEX ON fifteen(three);
CREATE INDEX ON fifteen(five);
ANALYZE fifteen;

EXPLAIN ANALYZE
SELECT*
FROM fifteen
WHERE three= 7
AND five =13
        ;

结果:

CREATE TABLE
INSERT 0 60000
CREATE INDEX
CREATE INDEX
ANALYZE
                                                              QUERY PLAN                                                               
---------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on fifteen  (cost=19.24..51.58 rows=31 width=12) (actual time=0.391..0.761 rows=364 loops=1)
   Recheck Cond: ((five = 13) AND (three = 7))
   Heap Blocks: exact=324
   ->  BitmapAnd  (cost=19.24..19.24 rows=31 width=0) (actual time=0.355..0.355 rows=0 loops=1)
         ->  Bitmap Index Scan on fifteen_five_idx  (cost=0.00..7.15 rows=1050 width=0) (actual time=0.136..0.136 rows=1091 loops=1)
               Index Cond: (five = 13)
         ->  Bitmap Index Scan on fifteen_three_idx  (cost=0.00..11.93 rows=1788 width=0) (actual time=0.194..0.194 rows=1819 loops=1)
               Index Cond: (three = 7)
 Planning time: 0.259 ms
 Execution time: 0.796 ms
(10 rows)

将{33,55}更改为{3,5}将仅在一个索引上生成索引扫描,并添加一个附加过滤条件。 (可能节省的成本太少了)