PostgreSQL上的CTE和临时索引

Mat*_*des 8 postgresql temp-tables jsonb postgresql-9.4

我在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
Run Code Online (Sandbox Code Playgroud)

好吧,我想知道是否有可能在这种表中创建临时索引,如果是,是否可以在jsonb类型fieds中创建索引?(考虑这个临时表)

IMS*_*SoP 10

很确定没有办法在CTE上创建索引,因为它基本上只是一个子查询,而不是表 - 它不会在任何地方保存在内存中,只是根据需要进入查询计划.

但你可以做Create Temp Table information As,然后索引,你的查询几乎没有变化.

您也可以索引物化视图,但如果您有下面的临时数据,那么创建另一个临时表可能最有意义.

  • 不幸的是,PostgreSQL目前无法暂时索引CTE术语.其他数据库产品可以这样做,它可以获得巨大的性能.没有根本原因我们不能这样做,但它在PostgreSQL中是复杂和侵入性的,因为规划者是统计和目录驱动的; 我们必须创建"可能的索引"路径,然后创建一个按需生成实际索引的计划节点. (9认同)
  • @IMSoP对于哈希或合并连接不可行的计划,动态索引可以是一个真正的胜利.你只需要构建一个b树,用它来完成你的工作并在最后扔掉它. (3认同)
  • @CraigRinger 嗯,我有点认为它在 CTE 的任何实现中都没有任何意义。原来我的答案只是偶然正确的! (2认同)
  • @CraigRinger:我很好奇:哪个DBMS可以在CTE上创建临时索引? (2认同)
  • “很确定没有办法在 CTE 上创建索引,因为它基本上只是一个子查询,而不是表 - 它不会持久保存在内存中的任何位置,只是根据需要滚动到查询计划中。” 这种说法是错误的,在 Postgres 12 之前,每个 CTE 都持久保存在内存中(如果太大则保存在磁盘上),它永远不是“根据需要滚动到查询计划中的子查询”。Postgres 12 使此行为可配置,即允许将 CTE 视为子查询 (2认同)

Str*_*das 6

不,您不能在查询期间对查询的某些部分创建索引。

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

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