37

我有一张有 450 万行的表格。没有主键。该表有一列p_id,类型为整数。使用该方法idx_mytable_p_id在此列上有一个索引。btree我愿意:

SELECT * FROM mytable WHERE p_id = 123456;

我对此进行了解释并看到以下输出:

Bitmap Heap Scan on mytable  (cost=12.04..1632.35 rows=425 width=321)
  Recheck Cond: (p_id = 543094)
  ->  Bitmap Index Scan on idx_mytable_p_id  (cost=0.00..11.93 rows=425 width=0)
        Index Cond: (p_id = 543094)

问题:

  • 为什么该查询先进行堆扫描,然后进行位图索引扫描?
  • 为什么要检查 425 行?为什么操作的宽度是321?
  • 12.04..1632.35 和 0.00..11.93 告诉我的成本是多少?

记录有 773 行,p_id值为 123456。 上有 38 列mytable

谢谢!

4

2 回答 2

56

为什么该查询先进行堆扫描,然后进行位图索引扫描?

它不是,确切地说。EXPLAIN 输出显示了执行节点的结构,“更高”级别的节点(没有缩进很远)从它们下面的节点中提取行。因此,当 Bitmap Heap Scan 节点开始提取其第一行时,Bitmap Index Scan 运行以确定要使用的行集,并将第一行的信息传递给堆扫描。索引扫描通过索引来确定需要读取哪些行,而堆扫描实际读取它们。这个想法是,通过从头到尾而不是按索引顺序读取堆,它将执行更少的随机访问——加载该页面时将读取来自给定页面的所有匹配行,并且可以读取足够多的页面以便使用更便宜的顺序访问,而不是在整个磁盘上来回查找。

为什么要检查 425 行?

它不是。您运行了 EXPLAIN,它只显示您的估计和选择的计划,它根本没有真正检查行。这使得 EXPLAIN 的值与运行 EXPLAIN ANALYZE 相比相当有限,EXPLAIN ANALYZE 实际运行查询并向您显示估计值和实际数字。

为什么操作的宽度是321?

显然这是mytable.

12.04..1632.35 和 0.00..11.93 告诉我的成本是多少?

第一个数字是从该节点返回第一行的成本;第二个数字是返回该节点的所有行的成本。请记住,这些是估计值。单位是抽象成本单位。绝对数字没有任何意义;计划中重要的是哪个计划成本最低。如果您使用光标,则第一个数字很重要;否则通常是第二个数字。(我认为它插入了一个 LIMIT 子句。)

通常需要调整可配置的成本因素,例如random_page_costcpu_tuple_cost,以便准确地对环境中的成本进行建模。如果没有这样的调整,比较成本可能与相应的运行时间不匹配,因此可能会选择不太理想的计划。

于 2012-04-13T17:51:50.717 回答
14

re 1) 执行计划必须从最内层节点读取到最外层节点。所以它首先进行索引扫描(查找行)并访问实际表以返回索引扫描找到的行

重新 2) 计划中显示的行数只是基于统计数据的估计,因此 425 与 773 听起来相当合理。如果您想查看真实数字,请使用explain analyze

re 3)成本图中的第一个数字是初始化计划者步骤的“启动”成本,第二个成本是该步骤的总成本。

这一切都记录在手册中: http ://www.postgresql.org/docs/current/static/using-explain.html

您可能还想浏览 PostgreSQL Wiki 中的这些链接:

PostgreSQL
解释使用解释

于 2012-04-13T17:43:32.323 回答