考虑 filtering/pagination 内部与外部子查询的 Postgres SQL 性能
Postgres SQL performance considering filtering/pagination inside vs outside subquery
我正在使用 Postgres 13.1,我想知道下面的查询 2 是否会影响性能。
考虑一个简单的 table 例如:
Table "Transaction"
Column | Type | Collation | Nullable | Default
----------------+--------------------------------+-----------+----------+-------------------
id | text | | not null |
amount | integer | | not null |
merchant_name | text | | not null |
考虑查询 1:
SELECT *
FROM Transaction
WHERE amount > 100
LIMIT 10;
考虑查询 2:
SELECT *
FROM (
SELECT *
FROM Transaction
) AS "result"
WHERE "result".amount > 100
LIMIT 10;
这两个查询具有相同的语义,最后找到相同的行。我的偏好是以查询 2 的格式编写许多查询,以将复杂的业务逻辑保留在子查询内,filtering/pagination 在子查询外。
但是,现在我担心的是:如果此 table 中有很多行,查询 2 的性能是否会比查询 1 差很多,或者它们的性能是否相同,因为这些 SQL语句最终会以相同的操作结束?
对于您的简单示例,没有问题。实际执行和优化的是有向无环图 (DAG),它与 SQL 语法没有明显关系。换句话说,查询的原始结构不会影响这种类型的优化。
具体的优化叫做predicate pushdown,意思是将过滤条件移动到子查询中。这将使查询能够使用索引。
Here 是一个示例,显示了两个版本的相同执行计划,无论是否有索引。
Postgres 确实支持谓词下推,但有一些注意事项:
- 它(不一定)与 CTE 或视图一起工作。
- 它不(必须)与聚合查询一起使用。
- 它(不一定)与基于集合的查询一起工作,例如
union all
。
“(必然)”是因为优化器是复杂的野兽,它们会随着数据库的不同版本而变化——以及依赖于为 table.
收集的统计数据之类的东西。
因此,对于示例中的特定查询,您可能是安全的;但是,作为一般原则,它可能并不安全。您可能希望在子查询中使用过滤条件来表达查询——或者至少检查解释计划以查看是否有必要。
我正在使用 Postgres 13.1,我想知道下面的查询 2 是否会影响性能。
考虑一个简单的 table 例如:
Table "Transaction"
Column | Type | Collation | Nullable | Default
----------------+--------------------------------+-----------+----------+-------------------
id | text | | not null |
amount | integer | | not null |
merchant_name | text | | not null |
考虑查询 1:
SELECT *
FROM Transaction
WHERE amount > 100
LIMIT 10;
考虑查询 2:
SELECT *
FROM (
SELECT *
FROM Transaction
) AS "result"
WHERE "result".amount > 100
LIMIT 10;
这两个查询具有相同的语义,最后找到相同的行。我的偏好是以查询 2 的格式编写许多查询,以将复杂的业务逻辑保留在子查询内,filtering/pagination 在子查询外。
但是,现在我担心的是:如果此 table 中有很多行,查询 2 的性能是否会比查询 1 差很多,或者它们的性能是否相同,因为这些 SQL语句最终会以相同的操作结束?
对于您的简单示例,没有问题。实际执行和优化的是有向无环图 (DAG),它与 SQL 语法没有明显关系。换句话说,查询的原始结构不会影响这种类型的优化。
具体的优化叫做predicate pushdown,意思是将过滤条件移动到子查询中。这将使查询能够使用索引。
Here 是一个示例,显示了两个版本的相同执行计划,无论是否有索引。
Postgres 确实支持谓词下推,但有一些注意事项:
- 它(不一定)与 CTE 或视图一起工作。
- 它不(必须)与聚合查询一起使用。
- 它(不一定)与基于集合的查询一起工作,例如
union all
。
“(必然)”是因为优化器是复杂的野兽,它们会随着数据库的不同版本而变化——以及依赖于为 table.
收集的统计数据之类的东西。因此,对于示例中的特定查询,您可能是安全的;但是,作为一般原则,它可能并不安全。您可能希望在子查询中使用过滤条件来表达查询——或者至少检查解释计划以查看是否有必要。