【发布时间】:2021-10-10 09:34:59
【问题描述】:
问题
使用 PostgreSQL 13,我遇到了一个性能问题,从连接两个表的视图中选择最高 id,具体取决于我执行的 select 语句。
这是一个示例设置:
CREATE TABLE test1 (
id BIGSERIAL PRIMARY KEY,
joincol VARCHAR
);
CREATE TABLE test2 (
joincol VARCHAR
);
CREATE INDEX ON test1 (id);
CREATE INDEX ON test1 (joincol);
CREATE INDEX ON test2 (joincol);
CREATE VIEW testview AS (
SELECT test1.id,
test1.joincol AS t1charcol,
test2.joincol AS t2charcol
FROM test1, test2
WHERE test1.joincol = test2.joincol
);
我发现了什么
我正在执行两个语句,这会导致完全不同的执行计划和运行时。以下语句在不到 100 毫秒内执行。据我了解执行计划,运行时与行数无关,因为 Postgres 会逐行迭代(从最高 id 开始,使用索引),直到可以连接一行并立即返回。
SELECT id FROM testview ORDER BY ID DESC LIMIT 1;
但是,在 Postgres 使用索引选择最高 id 之前,这两个表平均需要 1 秒以上(取决于行数),因为这两个表是“完全连接的”。
SELECT MAX(id) FROM testview;
请参阅 dbfiddle 上的此示例以查看解释计划:
https://www.db-fiddle.com/f/bkMNeY6zXqBAYUsprJ5eWZ/1
我的真实环境
在我的真实环境中,test1 仅包含一整行 (joincol 中具有唯一值。 test2 最多包含 ~10M 行,其中 joincol 始终匹配 test1 的 joincol 的值。 test2 的 joincol 不可为空。
实际问题
为什么 Postgres 无法识别它可以在第二个选择的行基础上使用 Index Scan Backward?表/索引有什么我可以改进的吗?
【问题讨论】:
-
附带说明:CREATE VIEW 语句中 SELECT 周围的括号完全没用
-
@a_horse_with_no_name 感谢您的提示。我喜欢使用这种风格,因为我的 IDE (IntelliJ IDEA) 应用了一些更好的颜色模式,使其更易于阅读。
-
然后 IntelliJ 对 SQL 的外观有一个非常奇怪的假设。它是否也对括号中的“独立”查询应用不同的颜色?例如:
(select 42);与select 42; -
@a_horse_with_no_name 不。着色基本上只是“分离”。当我的光标在括号内时,查询的“其他所有内容”都会稍微模糊
-
您的问题“为什么 postgres 会这样”的答案是:因为这就是它的优化器的编码方式。优化器并不完美,无法识别和/或执行一些它可以进行的转换。
标签: sql postgresql performance sql-execution-plan postgresql-performance