主键列是否包含在辅助索引的末尾

Rom*_*kin 4 postgresql indexing

鉴于这些表

Foo
 id (PK)
 name
 updated
Run Code Online (Sandbox Code Playgroud)
Bar
 foo_id (FK)
 name
 updated
Run Code Online (Sandbox Code Playgroud)

这个查询:

SELECT * 
FROM Foo as f
JOIN Bar as b
ON f.id=b.foo_id
WHERE b.name = 'Baz' AND f.name = 'Baz'
ORDER BY f.updated ASC, f.id ASC
LIMIT 10
OFFSET 10
Run Code Online (Sandbox Code Playgroud)

这些索引是否适合添加 - 在 MySql InnoDB 中,主键列会自动添加到辅助索引的末尾。Postgres 的情况如何?

CREATE INDEX foo_name_id_idx ON foo(name, id)
CREATE INDEX bar_name_id_idx ON bar(name, id)
Run Code Online (Sandbox Code Playgroud)

Lau*_*lbe 5

PostgreSQL不区分主、辅索引,主键索引与其他索引没有什么区别。因此主键不会添加到其他索引中,除非有特殊原因,否则这样做是没有意义的。

根据选择性的条件,存在三种可能的策略:

  1. 如果 on 的条件bar.name是选择性的,则使用bar作为驱动站点:

    CREATE INDEX ON bar (name);
    -- foo.id is already indexed
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果 on 的条件foo.name是选择性的:

    CREATE INDEX ON foo (name);
    CREATE INDEX ON bar(foo_id);  -- for a nested loop join
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果没有一个条件是可选的:

    /* here the "id" is actually at the end of the index,
       but that is just because it appears in ORDER BY */
    CREATE INDEX ON foo (name, updated, id);  -- for the ORDER BY
    CREATE INDEX ON bar (foo_id);  -- for a nested loop join
    
    Run Code Online (Sandbox Code Playgroud)