PostgreSQL:性能调优查询
Posted
技术标签:
【中文标题】PostgreSQL:性能调优查询【英文标题】:PostgreSQL: Performance Tuning a Query 【发布时间】:2021-10-11 07:58:04 【问题描述】:我有一个如下表:
表名称:Table_A
A_ID | A_Name |
---|---|
21 | XYZ |
22 | IJK |
表名称:Table_S1
S_ID | S_Name | A_ID |
---|---|---|
123 | ABC123 | 21 |
124 | PQR321 | 22 |
表名称:Table_S2
S_ID | S2_Date_1 | S2_Date_2 |
---|---|---|
123 | 01/01/2015 | 02/04/2016 |
124 | 01/01/2021 | 02/04/2018 |
123 | NULL | 02/04/2019 |
124 | 01/01/2017 | NULL |
Table_A 和 Table_S1 有主键,而 Table_S2 没有主键。
Table_S1.A_ID --> 引用到 --> Table_A 的主键 A_ID
Table_S2.S_ID --> 引用到 --> Table_S1 的主键 S_ID
Table_S1 表中大约有 400,000 条记录,Table_S1 中的每条记录有 120 条来自 Table_S2 的记录。这意味着 Table_S2 是一个包含大约 4800 万条记录的巨大表。
我需要使用如下 2 个不同的查询分别从 Table_S2 的 S2_Date_1 和 S2_Date_2 列中获取年份。
SELECT DISTINCT EXTRACT(YEAR FROM s2.S2_Date_1)
FROM Table_S2 s2, Table_S1 s1, Table_A a
WHERE s2.S_ID = s1.S_ID
AND s1.A_ID = a.A_ID
AND s1.B_ID = b.B_ID
AND a.A_Name = 'IJK';
如果我按 A_ID 分组,记录如下:
A_ID | Count_of_Table_S1 | Count_of_Table_S2 |
---|---|---|
21 | 100,000 | 12,000,000 |
22 | 150,000 | 18,000,000 |
23 | 90,000 | 10,800,000 |
Table_S2 上没有分区。从这些数百万条记录中获取所有年份大约需要 1 分钟,我的要求是在一秒钟内获取它们。这有可能做到这一点吗? 谁能建议一个最好的方法来做到这一点?
提前致谢。
【问题讨论】:
请显示EXPLAIN (ANALYZE, BUFFERS)
查询的输出,最好在设置track_io_timing = on
之后。
您似乎不需要连接表的任何列,将古老的隐式连接重写为 EXISTS 条件可能会提高性能。
您将无法在一秒钟内动态汇总那么多记录。使用物化视图。
【参考方案1】:
你有很多行要总结。可靠地将此时间缩短到一秒可能是不可能的。
您可以尝试将存储的生成列放在Table_S2
上,然后对其进行索引。
ALTER TABLE Table_S2
ADD COLUMN S2_Date1_Year
GENERATED ALWAYS AS EXTRACT(YEAR FROM s2.S2_Date_1)
STORED;
这给了你专栏。那么
ALTER TABLE TABLE_S2 ADD INDEX year_by_sid (S_ID, S2_Date1_Year);
添加索引。然后将您的查询更改为
SELECT DISTINCT s2.S2_Date1_Year ...
您的查询可能会更快,但不确定:它不必重新计算每一行的年份。
您可能想要一个物化视图。
CREATE MATERIALIZED VIEW View_S2_Year AS
SELECT DISTINCT S_ID, EXTRACT(YEAR FROM s2.S2_Date_1) AS S2_Date1_Year
FROM Table_S2;
CREATE INDEX year_by_sid ON View_S2_Year (S_ID, S2_Date1_Year);
然后加入 View_S2_Year 而不是 Table_S2。
注意:您需要不时刷新视图以使其与基表同步。在对基表进行更改后,其内容将是陈旧的,直到您刷新它为止。
REFRESH MATERIALIZED VIEW View_S2_Year;
【讨论】:
非常感谢大家。我会尝试这些方式,看看我是否可以让它像你提到的那样简单。将再次在这里分享结果。 :)以上是关于PostgreSQL:性能调优查询的主要内容,如果未能解决你的问题,请参考以下文章