PostgreSQL 上的 CTE 和临时索引

问题描述 投票:0回答:3

我在 postgres 数据库上工作,我将混合使用关系表和 jsonb 表(可以建立索引)。

我一直在使用大量 CTE 查询来插入或更新从临时表中选择的数据,例如:

WITH information as (
    select fieldA, fieldB, fieldC from tableA
)
insert (fieldA, fieldB, fieldC)
SELECT inf.fieldA, inf.fieldB, inf.fieldC
from information inf

嗯,我想知道是否可以在这种表中创建临时索引,如果可以,是否也可以在 jsonb 类型字段中创建索引? (考虑这个临时表)

postgresql temp-tables postgresql-9.4 jsonb
3个回答
22
投票

非常确定无法在 CTE 上创建索引,因为它基本上只是一个子查询,而不是表 - 它不会持久保存在内存中的任何位置,只是根据需要滚动到查询计划中。

但是您可以改为

Create Temp Table information As
,然后对其进行索引,而对查询的更改很少。

您还可以为物化视图建立索引,但如果您下面有临时数据,则仅创建另一个临时表可能最有意义。


6
投票

不可以,在查询期间,您无法对查询的各个部分创建索引。

CTE(公用表表达式),也称为子查询分解。 这个概念允许优化器为复杂查询生成执行计划,同时允许它通过将子查询放入临时空间而不是重新执行相同的步骤来减少子查询的重复。 将其放入单个查询中会生成一个大的步骤列表,这些步骤全部作为常规查询而不是作为过程执行。 它可以用作视图并在内存中存储执行计划。
选择不允许索引的部分原因是,它需要调用索引,然后必须针对主查询重新优化,或者更糟糕的是,执行计划必须留出空间来猜测哪一步执行。 由于我们已经有了可以建立索引的临时表,因此我相信它可以保持表的干净,从而使索引活动远离执行计划。 构建一个临时表,为其建立索引,然后当您运行查询时,它将具有新优化的执行计划。 另外,临时表可以在整个过程期间持续存在,cte 临时数据在查询完成后将被删除。

但是您仍然可以在 CTE 中使用临时表,因此它不是全部或全部。


0
投票

在 CTE 上没有直接创建索引的方法,但我们可以在简单查询中强制它通过其他方式使用索引,例如

With <CTE> as (Select * from <TableA> where <Conditions> ) select * from <CTE> inner join <TableA> on <Indexed Condition> Join  <Other Tables> to <TableA>
。 CTE 的过滤结果应再次与实际表连接,并且该表应用于进一步连接。除了
<TableA>
Join

之外,请勿进一步使用 CTE
© www.soinside.com 2019 - 2024. All rights reserved.