Skip to content

Commit 144bef7

Browse files
author
chegong18
committed
Update queries.sgml -200718
——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 &mdash; 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>
1 parent 68b79ed commit 144bef7

File tree

1 file changed

+141
-15
lines changed

1 file changed

+141
-15
lines changed

postgresql/doc/src/sgml/queries.sgml

Lines changed: 141 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,6 @@ ____________________________________________________________________________-->
547547

548548
<varlistentry>
549549
<term><literal>LEFT OUTER JOIN</literal>
550-
551550
<indexterm>
552551
<primary>连接</primary>
553552
<secondary>左</secondary>
@@ -567,7 +566,6 @@ ____________________________________________________________________________-->
567566

568567
<varlistentry>
569568
<term><literal>RIGHT OUTER JOIN</literal>
570-
571569
<indexterm>
572570
<primary>连接</primary>
573571
<secondary>右</secondary>
@@ -596,7 +594,7 @@ ____________________________________________________________________________-->
596594
</varlistentry>
597595
</variablelist>
598596
</para>
599-
597+
600598
<!--==========================orignal english content==========================
601599
<para>
602600
The <literal>ON</literal> clause is the most general kind of join
@@ -627,7 +625,7 @@ ____________________________________________________________________________-->
627625
<para>
628626
<literal>USING</literal>是个缩写符号,它允许你利用特殊的情况:连接的两端都具有相同的连接列名。它接受共享列名的一个逗号分隔列表,并且为其中每一个共享列构造一个包含等值比较的连接条件。例如用<literal>USING (a, b)</literal>连接<replaceable>T1</replaceable>和<replaceable>T2</replaceable>会产生连接条件<literal>ON <replaceable>T1</replaceable>.a = <replaceable>T2</replaceable>.a AND <replaceable>T1</replaceable>.b = <replaceable>T2</replaceable>.b</literal>。
629627
</para>
630-
628+
631629
<!--==========================orignal english content==========================
632630
<para>
633631
Furthermore, the output of <literal>JOIN USING</literal> suppresses
@@ -672,7 +670,7 @@ ____________________________________________________________________________-->
672670
</indexterm>
673671
最后,<literal>NATURAL</literal>是<literal>USING</literal>的缩写形式:它形成一个<literal>USING</literal>列表, 该列表由那些在两个表里都出现了的列名组成。和<literal>USING</literal>一样,这些列只在输出表里出现一次。如果不存在公共列,<literal>NATURAL JOIN</literal>的行为将和<literal>JOIN ... ON TRUE</literal>一样产生交叉集连接。
674672
</para>
675-
673+
676674
<note>
677675
<!--==========================orignal english content==========================
678676
<para>
@@ -2097,7 +2095,7 @@ ____________________________________________________________________________-->
20972095
如果一个查询包含聚集函数调用,但是没有<literal>GROUP BY</literal>子句,分组仍然会发生:结果是一个单一行(或者根本就没有行,如果该单一行被<literal>HAVING</literal>所消除)。它包含一个<literal>HAVING</literal>子句时也是这样,即使没有任何聚集函数调用或者<literal>GROUP BY</literal>子句。
20982096
</para>
20992097
</sect2>
2100-
2098+
21012099
<sect2 id="queries-grouping-sets">
21022100
<!--==========================orignal english content==========================
21032101
<title><literal>GROUPING SETS</literal>, <literal>CUBE</literal>, and <literal>ROLLUP</literal></title>
@@ -3232,7 +3230,7 @@ ____________________________________________________________________________-->
32323230
<para>
32333231
<literal>OFFSET</literal>说明在开始返回行之前忽略多少行。<literal>OFFSET 0</literal>的效果和省略<literal>OFFSET</literal>子句是一样的,并且<literal>LIMIT NULL</literal>的效果和省略<literal>LIMIT</literal>子句一样,就像是<literal>OFFSET</literal>带有 NULL 参数一样。
32343232
</para>
3235-
3233+
32363234
<!--==========================orignal english content==========================
32373235
<para>
32383236
If both <literal>OFFSET</literal>
@@ -3912,24 +3910,152 @@ SELECT n FROM t LIMIT 100;
39123910

39133911
<!--==========================orignal english content==========================
39143912
<para>
3915-
A useful property of <literal>WITH</literal> queries is that they are evaluated
3916-
only once per execution of the parent query, even if they are referred to
3917-
more than once by the parent query or sibling <literal>WITH</literal> queries.
3913+
A useful property of <literal>WITH</literal> queries is that they are
3914+
normally evaluated only once per execution of the parent query, even if
3915+
they are referred to more than once by the parent query or
3916+
sibling <literal>WITH</literal> queries.
39183917
Thus, expensive calculations that are needed in multiple places can be
39193918
placed within a <literal>WITH</literal> query to avoid redundant work. Another
39203919
possible application is to prevent unwanted multiple evaluations of
39213920
functions with side-effects.
3922-
However, the other side of this coin is that the optimizer is less able to
3923-
push restrictions from the parent query down into a <literal>WITH</literal> query
3924-
than an ordinary subquery. The <literal>WITH</literal> query will generally be
3921+
However, the other side of this coin is that the optimizer is not able to
3922+
push restrictions from the parent query down into a multiply-referenced
3923+
<literal>WITH</literal> query, since that might affect all uses of the
3924+
<literal>WITH</literal> query's output when it should affect only one.
3925+
The multiply-referenced <literal>WITH</literal> query will be
39253926
evaluated as written, without suppression of rows that the parent query
39263927
might discard afterwards. (But, as mentioned above, evaluation might stop
39273928
early if the reference(s) to the query demand only a limited number of
39283929
rows.)
39293930
</para>
39303931
____________________________________________________________________________-->
39313932
<para>
3932-
<literal>WITH</literal>查询的一个有用的特性是在每一次父查询的执行中它们只被计算一次,即使它们被父查询或兄弟<literal>WITH</literal>查询引用了超过一次。因此,在多个地方需要的昂贵计算可以被放在一个<literal>WITH</literal>查询中来避免冗余工作。另一种可能的应用是阻止不希望的多个函数计算产生副作用。但是,从另一方面来看,优化器不能将来自父查询的约束下推到<literal>WITH</literal>查询中而不是一个普通子查询。<literal>WITH</literal>查询通常将会被按照所写的方式计算,而不抑制父查询以后可能会抛弃的行(但是,如上所述,如果对查询的引用只请求有限数目的行,计算可能会提前停止)。
3933+
<literal>WITH</literal>查询的一个有用的特性是在每一次父查询的执行中它们通常只被计算一次,即使它们被父查询或兄弟<literal>WITH</literal>查询引用了超过一次。
3934+
因此,在多个地方需要的昂贵计算可以被放在一个<literal>WITH</literal>查询中来避免冗余工作。另一种可能的应用是阻止不希望的多个函数计算产生副作用。
3935+
但是,从另一方面来看,优化器不能将来自父查询的约束下推到乘法引用<literal>WITH</literal>查询,因为当他应该只影响一个时它可能会影响所有使用<literal>WITH</literal>查询的输出的使用。
3936+
乘法引用<literal>WITH</literal>查询通常将会被按照所写的方式计算,而不抑制父查询以后可能会抛弃的行(但是,如上所述,如果对查询的引用只请求有限数目的行,计算可能会提前停止)。
3937+
</para>
3938+
3939+
<!--==========================orignal english content==========================
3940+
<para>
3941+
However, if a <literal>WITH</literal> query is non-recursive and
3942+
side-effect-free (that is, it is a <literal>SELECT</literal> containing
3943+
no volatile functions) then it can be folded into the parent query,
3944+
allowing joint optimization of the two query levels. By default, this
3945+
happens if the parent query references the <literal>WITH</literal> query
3946+
just once, but not if it references the <literal>WITH</literal> query
3947+
more than once. You can override that decision by
3948+
specifying <literal>MATERIALIZED</literal> to force separate calculation
3949+
of the <literal>WITH</literal> query, or by specifying <literal>NOT
3950+
MATERIALIZED</literal> to force it to be merged into the parent query.
3951+
The latter choice risks duplicate computation of
3952+
the <literal>WITH</literal> query, but it can still give a net savings if
3953+
each usage of the <literal>WITH</literal> query needs only a small part
3954+
of the <literal>WITH</literal> query's full output.
3955+
</para>
3956+
____________________________________________________________________________-->
3957+
<para>
3958+
但是,如果 <literal>WITH</literal> 查询是非递归和边际效应无关的(就是说,它是一个<literal>SELECT</literal>包含没有可变函数),则它可以合并到父查询中,允许两个查询级别的联合优化。
3959+
默认情况下,这发生在如果父查询仅引用 <literal>WITH</literal>查询一次的时候,而不是它引用<literal>WITH</literal>查询多于一次时。
3960+
你可以超越控制这个决策,通过指定 <literal>MATERIALIZED</literal> 来强制分开计算 <literal>WITH</literal> 查询,或者通过指定 <literal>NOT MATERIALIZED</literal>来强制它被合并到父查询中。
3961+
后一种选择存在重复计算<literal>WITH</literal>查询的风险,但它仍然能提供净节省,如果<literal>WITH</literal>查询的每个使用只需要<literal>WITH</literal>查询的完整输出的一小部分。
3962+
</para>
3963+
3964+
<!--==========================orignal english content==========================
3965+
<para>
3966+
A simple example of these rules is
3967+
<programlisting>
3968+
WITH w AS (
3969+
SELECT * FROM big_table
3970+
)
3971+
SELECT * FROM w WHERE key = 123;
3972+
</programlisting>
3973+
This <literal>WITH</literal> query will be folded, producing the same
3974+
execution plan as
3975+
<programlisting>
3976+
SELECT * FROM big_table WHERE key = 123;
3977+
</programlisting>
3978+
In particular, if there's an index on <structfield>key</structfield>,
3979+
it will probably be used to fetch just the rows having <literal>key =
3980+
123</literal>. On the other hand, in
3981+
<programlisting>
3982+
WITH w AS (
3983+
SELECT * FROM big_table
3984+
)
3985+
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
3986+
WHERE w2.key = 123;
3987+
</programlisting>
3988+
the <literal>WITH</literal> query will be materialized, producing a
3989+
temporary copy of <structname>big_table</structname> that is then
3990+
joined with itself &mdash; without benefit of any index. This query
3991+
will be executed much more efficiently if written as
3992+
<programlisting>
3993+
WITH w AS NOT MATERIALIZED (
3994+
SELECT * FROM big_table
3995+
)
3996+
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
3997+
WHERE w2.key = 123;
3998+
</programlisting>
3999+
so that the parent query's restrictions can be applied directly
4000+
to scans of <structname>big_table</structname>.
4001+
</para>
4002+
____________________________________________________________________________-->
4003+
<para>
4004+
这些规则的一个简单示例是
4005+
<programlisting>
4006+
WITH w AS (
4007+
SELECT * FROM big_table
4008+
)
4009+
SELECT * FROM w WHERE key = 123;
4010+
</programlisting>
4011+
这个 <literal>WITH</literal> 查询将被合并,生成相同的执行计划为
4012+
<programlisting>
4013+
SELECT * FROM big_table WHERE key = 123;
4014+
</programlisting>
4015+
特别是,如果在<structfield>key</structfield>上有一个索引,它可能只用于获取具有 <literal>key = 123</literal>的行。 另一方面,在
4016+
<programlisting>
4017+
WITH w AS (
4018+
SELECT * FROM big_table
4019+
)
4020+
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
4021+
WHERE w2.key = 123;
4022+
</programlisting>
4023+
<literal>WITH</literal>查询将被物化,生成一个<structname>big_table</structname>的临时拷贝,然后与其自身 &mdash 联合;没有任何索引的益处。
4024+
这个查询将被执行的更有效率,如果写为
4025+
<programlisting>
4026+
WITH w AS NOT MATERIALIZED (
4027+
SELECT * FROM big_table
4028+
)
4029+
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
4030+
WHERE w2.key = 123;
4031+
</programlisting>
4032+
所以父查询的限制可以直接应用于<structname>big_table</structname>的扫描。
4033+
</para>
4034+
4035+
<!--==========================orignal english content==========================
4036+
<para>
4037+
An example where <literal>NOT MATERIALIZED</literal> could be
4038+
undesirable is
4039+
<programlisting>
4040+
WITH w AS (
4041+
SELECT key, very_expensive_function(val) as f FROM some_table
4042+
)
4043+
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.f = w2.f;
4044+
</programlisting>
4045+
Here, materialization of the <literal>WITH</literal> query ensures
4046+
that <function>very_expensive_function</function> is evaluated only
4047+
once per table row, not twice.
4048+
</para>
4049+
____________________________________________________________________________-->
4050+
<para>
4051+
一个<literal>NOT MATERIALIZED</literal> 可能不理想的例子为
4052+
<programlisting>
4053+
WITH w AS (
4054+
SELECT key, very_expensive_function(val) as f FROM some_table
4055+
)
4056+
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.f = w2.f;
4057+
</programlisting>
4058+
在这里,<literal>WITH</literal>查询的物化确保<function>very_expensive_function</function>每个表行只计算一次,而不是两次。
39334059
</para>
39344060

39354061
<!--==========================orignal english content==========================
@@ -4081,7 +4207,7 @@ WITH RECURSIVE included_parts(sub_part, part) AS (
40814207
SELECT p.sub_part, p.part
40824208
FROM included_parts pr, parts p
40834209
WHERE p.part = pr.sub_part
4084-
)
4210+
)
40854211
DELETE FROM parts
40864212
WHERE part IN (SELECT part FROM included_parts);
40874213
</programlisting>

0 commit comments

Comments
 (0)