“Plan Rows: 0”在 PostgreSQL 查询计划中是什么意思?

What does “Plan Rows: 0” mean in PostgreSQL query plan?

此查询在查询计划中显示 "Plan Rows: 0"。

CREATE TABLE EMP (
   EMP_ID CHAR(4),
   EMP_NAME VARCHAR(200)
);
INSERT INTO EMP VALUES ( '1000', 'JOHN DOE' );
INSERT INTO EMP VALUES ( '1001', 'ALAN SMITHEE' );
INSERT INTO EMP VALUES ( '1002', 'JANE DOE' );
EXPLAIN (ANALYZE, FORMAT JSON)
   SELECT * FROM EMP WHERE EMP_ID = NULL;

结果:

[ { "Plan": {
   "Node Type": "Result",
   "Parallel Aware": false,
   "Startup Cost": 0.00,
   "Total Cost": 0.00,
   "Plan Rows": 0,
   "Plan Width": 438,
   "Actual Startup Time": 0.001,
   "Actual Total Time": 0.001,
   "Actual Rows": 0,
   "Actual Loops": 1,
   "One-Time Filter": "false"
},
"Planning Time": 0.023,
"Triggers": [ ],
"Execution Time": 0.011 } ]

这个查询计划中的 "Plan Rows: 0" 是什么意思?

  1. PostgreSQL 没有扫描任何记录,因为 EMP_ID = NULL 总是假的。
  2. PostgreSQL 扫描了 EMP table,因为统计信息可能与实际 table 内容不同。

分析将每次扫描 table,因为您的条件始终为 false,所以它总是 return 0 计划行。如果您在不截断 table 的情况下继续插入行,您将看到成本随着行数的增加而开始增加,这是由于检查 where 条件所花费的额外时间。

来自文档 https://www.postgresql.org/docs/9.2/static/using-explain.html:

The rows value is a little tricky because it is not the number of rows processed or scanned by the plan node, but rather the number emitted by the node. This is often less than the number scanned, as a result of filtering by any WHERE-clause conditions that are being applied at the node. Ideally the top-level rows estimate will approximate the number of rows actually returned, updated, or deleted by the query.

来自链接文档中显示的示例:

Notice that the EXPLAIN output shows the WHERE clause being applied as a "filter" condition attached to the Seq Scan plan node. This means that the plan node checks the condition for each row it scans, and outputs only the ones that pass the condition. The estimate of output rows has been reduced because of the WHERE clause. However, the scan will still have to visit all 10000 rows, so the cost hasn't decreased; in fact it has gone up a bit (by 10000 * cpu_operator_cost, to be exact) to reflect the extra CPU time spent checking the WHERE condition.

PostgreSQL 检测到 emp_id = NULL 始终为 false,因此它根本不扫描 table,但 returns 立即得到一个空结果。

“计划行”是估计的结果行数,为 0,因为 PostgreSQL 知道 不能有结果行。通常,当 PostgreSQL 不能确定时,它会至少估计一个结果,以避免在估计错误的情况下做出非常糟糕的计划。