Postgresql 为什么这个简单的SQL查询这么慢?

Postgresql 为什么这个简单的SQL查询这么慢?,postgresql,Postgresql,我有一个问题 select p.id from Product p,Identifier i where p.id=i.product_id and p.aggregatorId='5109037' and p.deletionDate is null and i.type='03' and i.value='9783639382891' 运行大约需要3.5秒。该产品约有470万条条目,标识符约2000万条。正如您在下面的模式中所看到的,查询中使用的每一列都被索引,但并不是所有的索

我有一个问题

select p.id 
from Product p,Identifier i 
where p.id=i.product_id 
and p.aggregatorId='5109037' 
and p.deletionDate is null
and i.type='03' 
and i.value='9783639382891' 
运行大约需要3.5秒。该产品约有470万条条目,标识符约2000万条。正如您在下面的模式中所看到的,查询中使用的每一列都被索引,但并不是所有的索引都被使用。如果排除列
p.aggregatorId
I.type
,则查询的运行速度与我预期的一样快。我还尝试加入标识符表,但解释计划没有改变

为什么不使用索引

解释计划如下所示:

Nested Loop  (cost=3.21..63.48 rows=1 width=33) (actual time=10.856..3236.830 rows=1 loops=1)
  ->  Index Scan using idx_prod_aggr on product p  (cost=0.43..2.45 rows=1 width=33) (actual time=0.041..191.339 rows=146692 loops=1)
        Index Cond: ((aggregatorid)::text = '5109037'::text)
        Filter: (deletiondate IS NULL)
  ->  Bitmap Heap Scan on identifier i  (cost=2.78..61.01 rows=1 width=33) (actual time=0.019..0.019 rows=0 loops=146692)
        Recheck Cond: ((product_id)::text = (p.id)::text)
        Filter: (((type)::text = '03'::text) AND ((value)::text = '9783639382891'::text))
        Rows Removed by Filter: 2"
        ->  Bitmap Index Scan on idx_id_prod_id  (cost=0.00..2.78 rows=29 width=0) (actual time=0.016..0.016 rows=2 loops=146692)
              Index Cond: ((product_id)::text = (p.id)::text)
CREATE TABLE product
(
  id character varying(32) NOT NULL,
  version integer,
  active boolean,
  aggregatorid character varying(15),
  deletiondate timestamp without time zone,
)
WITH (
  OIDS=FALSE
);

CREATE INDEX idx_prod_active
  ON product
  USING btree
  (active);

CREATE INDEX idx_prod_aggr
  ON product
  USING btree
  (aggregatorid COLLATE pg_catalog."default");

CREATE INDEX idx_prod_del_date
  ON product
  USING btree
  (deletiondate);



CREATE TABLE identifier
(
  id character varying(32) NOT NULL,
  version integer,
  typename character varying(50),
  type character varying(3) NOT NULL,
  value character varying(512) NOT NULL,
  product_id character varying(32),
  CONSTRAINT identifier_pkey PRIMARY KEY (id),
  CONSTRAINT fk165a88c9c93f3e7f FOREIGN KEY (product_id)
      REFERENCES product (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);

CREATE INDEX idx_id_prod_type
  ON identifier
  USING btree
  (type COLLATE pg_catalog."default");

CREATE INDEX idx_id_prod_value
  ON identifier
  USING btree
  (value COLLATE pg_catalog."default");

CREATE INDEX idx_id_typename
  ON identifier
  USING btree
  (typename COLLATE pg_catalog."default");

CREATE INDEX idx_prod_ident
  ON identifier
  USING btree
  (product_id COLLATE pg_catalog."default");
简化的DB模式如下所示:

Nested Loop  (cost=3.21..63.48 rows=1 width=33) (actual time=10.856..3236.830 rows=1 loops=1)
  ->  Index Scan using idx_prod_aggr on product p  (cost=0.43..2.45 rows=1 width=33) (actual time=0.041..191.339 rows=146692 loops=1)
        Index Cond: ((aggregatorid)::text = '5109037'::text)
        Filter: (deletiondate IS NULL)
  ->  Bitmap Heap Scan on identifier i  (cost=2.78..61.01 rows=1 width=33) (actual time=0.019..0.019 rows=0 loops=146692)
        Recheck Cond: ((product_id)::text = (p.id)::text)
        Filter: (((type)::text = '03'::text) AND ((value)::text = '9783639382891'::text))
        Rows Removed by Filter: 2"
        ->  Bitmap Index Scan on idx_id_prod_id  (cost=0.00..2.78 rows=29 width=0) (actual time=0.016..0.016 rows=2 loops=146692)
              Index Cond: ((product_id)::text = (p.id)::text)
CREATE TABLE product
(
  id character varying(32) NOT NULL,
  version integer,
  active boolean,
  aggregatorid character varying(15),
  deletiondate timestamp without time zone,
)
WITH (
  OIDS=FALSE
);

CREATE INDEX idx_prod_active
  ON product
  USING btree
  (active);

CREATE INDEX idx_prod_aggr
  ON product
  USING btree
  (aggregatorid COLLATE pg_catalog."default");

CREATE INDEX idx_prod_del_date
  ON product
  USING btree
  (deletiondate);



CREATE TABLE identifier
(
  id character varying(32) NOT NULL,
  version integer,
  typename character varying(50),
  type character varying(3) NOT NULL,
  value character varying(512) NOT NULL,
  product_id character varying(32),
  CONSTRAINT identifier_pkey PRIMARY KEY (id),
  CONSTRAINT fk165a88c9c93f3e7f FOREIGN KEY (product_id)
      REFERENCES product (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);

CREATE INDEX idx_id_prod_type
  ON identifier
  USING btree
  (type COLLATE pg_catalog."default");

CREATE INDEX idx_id_prod_value
  ON identifier
  USING btree
  (value COLLATE pg_catalog."default");

CREATE INDEX idx_id_typename
  ON identifier
  USING btree
  (typename COLLATE pg_catalog."default");

CREATE INDEX idx_prod_ident
  ON identifier
  USING btree
  (product_id COLLATE pg_catalog."default");

.rows=1..
rows=146692
的对比看起来不太好。你的统计数据是最新的吗?运行
分析产品
会改变什么吗?谢谢!在两个表上运行analyze就成功了。但这让我很惊讶,因为我们已经启动了自动真空任务。我想,我们必须检查一下设置;)您是否只是将数据加载到表中(例如,夜间批处理加载?)是的,我们有一些较大的导入每晚运行。注意:
varchar(32)
PK和FK组件在我看来是次要的。可以由代理键+唯一约束替换。