You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
——row3915至3918,调英为:
A useful property of <literal>WITH</literal> queries is that they are
normally evaluated only once per execution of the parent query, even if
they are referred to more than once by the parent query or
sibling <literal>WITH</literal> queries.
Thus, expensive calculations that are needed in multiple places can be
placed within a <literal>WITH</literal> query to avoid redundant work. Another
possible application is to prevent unwanted multiple evaluations of
functions with side-effects.
However, the other side of this coin is that the optimizer is not able to
push restrictions from the parent query down into a multiply-referenced
<literal>WITH</literal> query, since that might affect all uses of the
<literal>WITH</literal> query's output when it should affect only one.
The multiply-referenced <literal>WITH</literal> query will be
evaluated as written, without suppression of rows that the parent query
might discard afterwards. (But, as mentioned above, evaluation might stop
early if the reference(s) to the query demand only a limited number of
rows.)
——row3933,调翻为:
<literal>WITH</literal>查询的一个有用的特性是在每一次父查询的执行中它们通常只被计算一次,即使它们被父查询或兄弟<literal>WITH</literal>查询引用了超过一次。
因此,在多个地方需要的昂贵计算可以被放在一个<literal>WITH</literal>查询中来避免冗余工作。另一种可能的应用是阻止不希望的多个函数计算产生副作用。
但是,从另一方面来看,优化器不能将来自父查询的约束下推到乘法引用<literal>WITH</literal>查询,因为当他应该只影响一个时它可能会影响所有使用<literal>WITH</literal>查询的输出的使用。
乘法引用<literal>WITH</literal>查询通常将会被按照所写的方式计算,而不抑制父查询以后可能会抛弃的行(但是,如上所述,如果对查询的引用只请求有限数目的行,计算可能会提前停止)。
——row3941至4061,增英和翻为:
<!--==========================orignal english content==========================
<para>
However, if a <literal>WITH</literal> query is non-recursive and
side-effect-free (that is, it is a <literal>SELECT</literal> containing
no volatile functions) then it can be folded into the parent query,
allowing joint optimization of the two query levels. By default, this
happens if the parent query references the <literal>WITH</literal> query
just once, but not if it references the <literal>WITH</literal> query
more than once. You can override that decision by
specifying <literal>MATERIALIZED</literal> to force separate calculation
of the <literal>WITH</literal> query, or by specifying <literal>NOT
MATERIALIZED</literal> to force it to be merged into the parent query.
The latter choice risks duplicate computation of
the <literal>WITH</literal> query, but it can still give a net savings if
each usage of the <literal>WITH</literal> query needs only a small part
of the <literal>WITH</literal> query's full output.
</para>
____________________________________________________________________________-->
<para>
但是,如果 <literal>WITH</literal> 查询是非递归和边际效应无关的(就是说,它是一个<literal>SELECT</literal>包含没有可变函数),则它可以合并到父查询中,允许两个查询级别的联合优化。
默认情况下,这发生在如果父查询仅引用 <literal>WITH</literal>查询一次的时候,而不是它引用<literal>WITH</literal>查询多于一次时。
你可以超越控制这个决策,通过指定 <literal>MATERIALIZED</literal> 来强制分开计算 <literal>WITH</literal> 查询,或者通过指定 <literal>NOT MATERIALIZED</literal>来强制它被合并到父查询中。
后一种选择存在重复计算<literal>WITH</literal>查询的风险,但它仍然能提供净节省,如果<literal>WITH</literal>查询的每个使用只需要<literal>WITH</literal>查询的完整输出的一小部分。
</para>
<!--==========================orignal english content==========================
<para>
A simple example of these rules is
<programlisting>
WITH w AS (
SELECT * FROM big_table
)
SELECT * FROM w WHERE key = 123;
</programlisting>
This <literal>WITH</literal> query will be folded, producing the same
execution plan as
<programlisting>
SELECT * FROM big_table WHERE key = 123;
</programlisting>
In particular, if there's an index on <structfield>key</structfield>,
it will probably be used to fetch just the rows having <literal>key =
123</literal>. On the other hand, in
<programlisting>
WITH w AS (
SELECT * FROM big_table
)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
WHERE w2.key = 123;
</programlisting>
the <literal>WITH</literal> query will be materialized, producing a
temporary copy of <structname>big_table</structname> that is then
joined with itself — without benefit of any index. This query
will be executed much more efficiently if written as
<programlisting>
WITH w AS NOT MATERIALIZED (
SELECT * FROM big_table
)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
WHERE w2.key = 123;
</programlisting>
so that the parent query's restrictions can be applied directly
to scans of <structname>big_table</structname>.
</para>
____________________________________________________________________________-->
<para>
这些规则的一个简单示例是
<programlisting>
WITH w AS (
SELECT * FROM big_table
)
SELECT * FROM w WHERE key = 123;
</programlisting>
这个 <literal>WITH</literal> 查询将被合并,生成相同的执行计划为
<programlisting>
SELECT * FROM big_table WHERE key = 123;
</programlisting>
特别是,如果在<structfield>key</structfield>上有一个索引,它可能只用于获取具有 <literal>key = 123</literal>的行。 另一方面,在
<programlisting>
WITH w AS (
SELECT * FROM big_table
)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
WHERE w2.key = 123;
</programlisting>
<literal>WITH</literal>查询将被物化,生成一个<structname>big_table</structname>的临时拷贝,然后与其自身 &mdash 联合;没有任何索引的益处。
这个查询将被执行的更有效率,如果写为
<programlisting>
WITH w AS NOT MATERIALIZED (
SELECT * FROM big_table
)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
WHERE w2.key = 123;
</programlisting>
所以父查询的限制可以直接应用于<structname>big_table</structname>的扫描。
</para>
<!--==========================orignal english content==========================
<para>
An example where <literal>NOT MATERIALIZED</literal> could be
undesirable is
<programlisting>
WITH w AS (
SELECT key, very_expensive_function(val) as f FROM some_table
)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.f = w2.f;
</programlisting>
Here, materialization of the <literal>WITH</literal> query ensures
that <function>very_expensive_function</function> is evaluated only
once per table row, not twice.
</para>
____________________________________________________________________________-->
<para>
一个<literal>NOT MATERIALIZED</literal> 可能不理想的例子为
<programlisting>
WITH w AS (
SELECT key, very_expensive_function(val) as f FROM some_table
)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.f = w2.f;
</programlisting>
在这里,<literal>WITH</literal>查询的物化确保<function>very_expensive_function</function>每个表行只计算一次,而不是两次。
</para>
0 commit comments