【问题标题】:Slow join performance in Postgresql with large tables具有大表的 Postgresql 中的连接性能缓慢
【发布时间】:2019-11-26 04:40:45
【问题描述】:

我使用以下代码设置我的 Postgresql 数据库,这将在 test1 表和 test2 表中创建 1000 万条记录。

CREATE TABLE test1(
    id serial PRIMARY KEY,
    val text
);

CREATE TABLE test2(
    test1_id integer,
    FOREIGN KEY (test1_id) REFERENCES test1(id)
);

do $$
begin
for r in 1..10000000 loop
  insert into test1(id, val) values(r, 10000000-1);
  insert into test2(test1_id) values(r);
end loop;
end;
$$;

CREATE INDEX test1_val ON test1 USING btree(val);

现在我执行以下连接:

SELECT * FROM test1 join test2 ON test1.id=test2.test1_id WHERE val='55555';

并且连接需要超过 1 秒才能完成。

这是在查询上运行解释的输出:

                                     QUERY PLAN
------------------------------------------------------------------------------------
 Hash Join  (cost=8.46..181757.13 rows=1 width=15)
   Hash Cond: (test2.test1_id = test1.id)
   ->  Seq Scan on test2  (cost=0.00..144248.48 rows=10000048 width=4)
   ->  Hash  (cost=8.45..8.45 rows=1 width=11)
         ->  Index Scan using test1_val on test1  (cost=0.44..8.45 rows=1 width=11)
               Index Cond: (val = '55555'::text)
(6 rows)

该示例更多用于说明目的,在真实场景中 test2 表上会有更多属性。同样在真实场景中,test1 和 test2 上的记录可能会更多,并且连接完成所需的时间会超过 1 秒。

有没有更有效的方法来构建这个数据库的索引,或者执行上面的查询?

【问题讨论】:

    标签: sql postgresql join indexing


    【解决方案1】:

    你忘了index the foreign key

    CREATE INDEX ON test2(test1_id);
    

    【讨论】:

    • 啊,我太不聪明了!出于某种原因,我认为添加外键会自动创建一个索引。
    • 不,不应该。在某些情况下,您不需要索引,可能是因为it is never used,也可能是因为表太小。
    • 好的,感谢您的意见。我的实际数据库的连接性能仍然很慢,但我会尝试提出另一个更准确地反映真实数据库的问题。
    • 您应该使用真实查询和查询的EXPLAIN (ANALYZE, BUFFERS) 输出开始一个新问题。
    • 有趣。在我的数据库服务器上,我遇到了查询缓慢的问题,然后我运行了EXPLAIN(ANALYZE, BUFFERS),之后查询开始快速运行。
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 2016-06-24
    • 1970-01-01
    • 2015-10-06
    相关资源
    最近更新 更多