连接的查询运行时间过长-Postgresql

连接的查询运行时间过长-Postgresql,sql,postgresql,postgresql-10,Sql,Postgresql,Postgresql 10,我有一个疑问,运行时间太长了。 我正在使用PostgreSQL 10.3。 在这个查询涉及的表中,每个表中大约有350万条记录。 查询是: SELECT thf.attr1, thf.attr2, thf.attr3, thf.attr4 FROM tb_one AS thf INNER JOIN tb_two AS ths ON ths.tb_hit_hitid = thf.tb_hit_hitid WHERE ths.source IN ('source1', 'source2') 在这些

我有一个疑问,运行时间太长了。 我正在使用PostgreSQL 10.3。 在这个查询涉及的表中,每个表中大约有350万条记录。 查询是:

SELECT thf.attr1, thf.attr2, thf.attr3, thf.attr4
FROM tb_one AS thf
INNER JOIN tb_two AS ths
ON ths.tb_hit_hitid = thf.tb_hit_hitid
WHERE ths.source IN ('source1', 'source2')
在这些表中,我有索引:

CREATE INDEX tb_two_idx_1 on tb_two (Source ASC, attr5 ASC);
CREATE INDEX tb_one_idx_1 on tb_one USING btree (attr1 ASC,attr2 ASC,attr3 ASC,attr4 ASC);
CREATE INDEX tb_one_idx_2 on tb_hit_feature (tb_hit_HitId ASC);
CREATE INDEX tb_two_idx_2 on tb_hit_source (tb_hit_HitId ASC);
这是查询计划(
explain(analysis,buffers)
):

对于此查询:

SELECT thf.attr1, thf.attr2, thf.attr3, thf.attr4
FROM tb_one thf INNER JOIN
     tb_two ths
     ON ths.tb_hit_hitid = thf.tb_hit_hitid
WHERE ths.source IN ('source1', 'source2');
您需要在
tb\u-two(源、tb\u-hitid)
tb\u-one(tb\u-hitid)
上建立索引。这可能是最好的指数

如果查询返回重复的结果(由于连接),我建议这样写:

SELECT thf.attr1, thf.attr2, thf.attr3, thf.attr4
FROM tb_one thf
WHERE EXISTS (SELECT 1
              FROM tb_two ths
              WHERE ths.tb_hit_hitid = thf.tb_hit_hitid AND
                    ths.source IN ('source1', 'source2')
             );

对于这个版本,您希望索引是
tb\u-two(tb\u-hit\u-hitid,source)

取决于值的分布,是不是
tb\u-two(tb\u-hit\u-hitid,source)
会更好?@AndrewLazarus。第一个问题?我对此表示怀疑。您可能希望首先按
where
子句进行筛选。我的意思是,我想索引顺序可能没有什么不同,但是通常情况下,
where
上的过滤器将是第一个。-我的想法是,
thf.source
的不同值可能太少,不值得索引,而连接可能是高度选择性的。您的where条件根据第二个表从一个表中选择大约180万行。我不知道你期望它有什么样的表现——这个计划非常适合这些条件。这可能是因为您的工作量太低,数据库必须使用磁盘作为临时文件-您可以发布
explain(analyze,verbose,buffers)选择…
进行确认。
SELECT thf.attr1, thf.attr2, thf.attr3, thf.attr4
FROM tb_one thf
WHERE EXISTS (SELECT 1
              FROM tb_two ths
              WHERE ths.tb_hit_hitid = thf.tb_hit_hitid AND
                    ths.source IN ('source1', 'source2')
             );