假设您有一个包含某些索引的表:
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会选择一个还是在某些情况下可以同时使用它们?
这不是关于特定查询的问题。理解内部结构是一个普遍的问题。
答案 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}将仅在一个索引上生成索引扫描,并添加一个附加过滤条件。 (可能节省的成本太少了)