sql - 此查询会将整个表加载到内存中吗

标签 sql sql-server postgresql

如果我有一个非常大的表,这个查询会在过滤重置之前将整个表加载到内存中:

with parent as
(
    select * from a101
)
select * from parent 
where value1 = 159

如您所见,父查询引用了整个表。将此加载到内存中。这是一个非常简化的查询版本。真正的查询有一些与其他表的连接。我正在评估 sql server 2012 和 postgrsql。

最佳答案

在 PostgreSQL 中(至少从 9.4 开始是正确的)CTEs act as optimisation fences .

即使在微不足道的情况下,查询优化器也不会将 CTE 术语扁平化到外部查询、下推限定词或拉出限定词。因此,CTE 术语中的非限定 SELECT 将始终执行全表扫描(如果有合适的索引,则执行仅索引扫描)。

因此,在 PostgreSQL 中,这两者确实非常不同,正如一个简单的 EXPLAIN 会显示的那样:

with parent as
(
    select * from a101
)
select * from parent 
where value1 = 159

SELECT *
FROM 
(
   SELECT * FROM a101
) AS parent
WHERE value1 = 159;

然而,“将扫描整个表”并不一定意味着“将整个表加载到内存中”。 PostgreSQL 将使用 TupleStore,随着它变大,它会透明地溢出到磁盘上的临时文件。

最初的理由是 CTE 术语中的 DML 已计划(后来实现)。如果 CTE 术语中有 DML,那么它的执行是可预测的和完整的是至关重要的。如果 CTE 调用数据修改函数,这也可能成立。

不幸的是,似乎没有人认为“......但是如果它只是一个 SELECT 而我们想要内联它呢?”

社区中的许多人似乎将此视为一项功能,并定期将其作为优化程序问题的解决方法进行公布。我觉得这种态度非常令人困惑。因此,以后很难解决这个问题,因为人们在想要防止优化器更改查询时会故意使用 CTE。

换句话说,PostgreSQL 将 CTE 滥用为伪查询提示(连同 OFFSET 0 hack),因为项目政策表明不需要或不支持真正的查询提示。

AFAIK MS SQL Server 可以优化 CTE 障碍,但也可以选择具体化结果集。

关于sql - 此查询会将整个表加载到内存中吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22626105/

相关文章:

sql - 结构化查询语言中的 "Structured"是什么?

PHP PDO 和使用 SELECT COUNT(*) 的查询

sql-server - 同时更新两个不同的数据库

sql - 是否可以在没有文件的情况下使用sql server批量插入?

PostgreSql命令查看表数据

Postgresql:可能在 lob 内进行全文搜索吗?

node.js - Sequelize count fn 添加 where 子句

SQL - 显示一条记录是否是在另一条记录之后创建的

MYSQL:BAD_FIELD_ERROR 'field list' 中的未知列

sql-server - 如何在 T-SQL/SQL Server 中模拟超/子类型(继承)实体的 BEFORE INSERT 触发器?