简体   繁体   English

为什么 PostgreSQL 11 优化器拒绝使用包含列的索引的最佳计划?

[英]Why is PostgreSQL 11 optimizer refusing best plan which would use an index w/ included column?

PostgreSQL 11 isn't smart enough to use indexes with included columns? PostgreSQL 11 不够聪明,无法使用包含列的索引?

CREATE INDEX organization_locations__org_id_is_headquarters__inc_location_id_ix
ON organization_locations(org_id, is_headquarters) INCLUDE (location_id);

ANALYZE organization_locations;
ANALYZE organizations;

EXPLAIN VERBOSE
SELECT location_id
FROM organization_locations ol
WHERE org_id = (SELECT id FROM organizations WHERE code = 'akron')
AND is_headquarters = 1;
QUERY PLAN
Seq Scan on organization_locations ol  (cost=8.44..14.61 rows=1 width=4)
  Output: ol.location_id
  Filter: ((ol.org_id = $0) AND (ol.is_headquarters = 1))
  InitPlan 1 (returns $0)
    ->  Index Scan using organizations__code_ux on organizations  (cost=0.42..8.44 rows=1 width=4)
          Output: organizations.id
          Index Cond: ((organizations.code)::text = 'akron'::text)

There are only 211 rows currently in organization_locations, average row length 91 bytes. organization_locations 目前只有 211 行,平均行长 91 字节。

I get only loading one data page.我只加载一个数据页。 But the I/O is the same to grab the index page and the target data is right there (no extra lookup into the data page from the index).但是获取索引页的 I/O 相同,并且目标数据就在那里(无需从索引中额外查找数据页)。 What is PG thinking with this plan? PG对这个计划有什么想法?

This just creates a TODO for me to round back and check to make sure the right plan starts getting generated once the table burgeons.这只是为我创建了一个待办事项,以便我回过头来检查以确保一旦表格迅速发展就开始生成正确的计划。

EDIT: Here is the explain with buffers:编辑:这是缓冲区的解释:

Seq Scan on organization_locations ol  (cost=8.44..14.33 rows=1 width=4) (actual time=0.018..0.032 rows=1 loops=1)
  Filter: ((org_id = $0) AND (is_headquarters = 1))
  Rows Removed by Filter: 210
  Buffers: shared hit=7
  InitPlan 1 (returns $0)
    ->  Index Scan using organizations__code_ux on organizations  (cost=0.42..8.44 rows=1 width=4) (actual time=0.008..0.009 rows=1 loops=1)
          Index Cond: ((code)::text = 'akron'::text)
          Buffers: shared hit=4
Planning Time: 0.402 ms
Execution Time: 0.048 ms

Reading one index page is not cheaper than reading a table page, so with tiny tables you cannot expect a gain from an index-only scan.读取一个索引页并不比读取一个表页便宜,因此对于小型表,您不能指望从仅索引扫描中获得收益。

Besides, did you另外,你有没有

VACUUM organization_locations;

Without that, the visibility map won't show that the table block is all-visible, so you cannot get an index-only scan no matter what.没有它,可见性 map 不会显示表块是全可见的,因此无论如何您都无法获得仅索引扫描。

In addition to the other answers, this is probably a silly index to have in the first place.除了其他答案之外,这可能是一个愚蠢的索引。 INCLUDE is good when you need a unique index but you also want to tack on a column which is not part of the unique constraint, or when the included column doesn't have btree operators and so can't be in the main body of the index.当您需要唯一索引但您还想添加不属于唯一约束的列时,或者当包含的列没有 btree 运算符因此不能在主体中时,INCLUDE 很好指数。 In other cases, you should just put the extra column in the index itself.在其他情况下,您应该只将额外的列放在索引本身中。

This just creates a TODO for me to round back and check to make sure the right plan starts getting generated once the table burgeons.这只是为我创建了一个待办事项,以便我回过头来检查以确保一旦表格迅速发展就开始生成正确的计划。

This is your workflow problem that you can't expect PostgreSQL to solve for you.这是您不能指望 PostgreSQL 为您解决的工作流程问题。 Do you really think PostgreSQL should create actual plans based on imaginary scenarios?您真的认为 PostgreSQL 应该根据想象的场景制定实际计划吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么优化器在联接时不使用索引查找 - Why Optimizer Does Not Use Index Seek on Join 为什么左连接会导致优化器忽略索引? - Why would a left join cause an optimizer to ignore an index? 优化器拒绝使用索引 - optimizer refuses to use the index 为什么MySQL优化器不使用所有列索引? - Why MySQL optimizer doesn't use all columns index? 用于排序结果的列是否应该包含在 postgresql 表的索引中? - Should the column used to order results be included in the index of a postgresql table? 如何使PostgresQL优化器在绑定参数后构建执行计划? - How to make PostgresQL optimizer to build execution plan AFTER binding parameters? 哪个运算符最适合用于解决此查询 - which operator would be best to use for solving this query DBMS 优化器 - 最佳执行计划,无论查询的公式如何 - DBMS optimizer - best execution plan, no matter the query's formulation 当计划中未使用该索引时,为什么在SQL Server中添加索引会减慢查询速度? - Why would the addition of an index in SQL Server slow a query, when that index is not used in the plan? PostgreSQL Optimizer如何处理交叉列关联 - how cross column correlation is handled by PostgreSQL Optimizer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM