在一个典型的很多很多这样的安排...

Movies       Actors       Movies_Actors
------       ------       -------------
movie_ID     actor_ID     FK_movie_ID
title        name         FK_actor_ID

... 关联表('Movies_Actors')应该如何索引以获得最佳读取速度?

我通常认为,这只能通过关联表中的复合主键来实现,如下所示:

CREATE TABLE Movies_Actors (
  FK_movie_ID INTEGER,
  FK_actor_ID INTEGER,
  PRIMARY KEY (FK_movie_ID, FK_actor_ID)
)

然而,这似乎只有在搜索bothmovie_IDactor_ID时索引才有用(尽管我不确定复合索引是否也适用于单个列).

由于"电影X中的演员是什么"和"演员Y中的演员是什么电影"将是此表的常见查询,因此似乎每个列上都应该有一个单独的索引,以便快速查找演员和电影.综合指数能有效地做到这一点吗?如果没有,那么在这个表上,拥有一个复合索引似乎毫无意义.如果复合索引没有意义,那么主键该怎么办?候选键显然是两列的组合,但如果生成的组合索引是无意义的(一定不是吗?)这似乎是浪费.

此外,this link增加了一些混乱,并表明它甚至可能有助于实际指定two个综合指数...其中一个是(FK_movie_ID, FK_actor_ID),另一个是(FK_actor_ID, FK_movie_ID), Select 哪个是主键(因此通常是聚集的),哪个"只是"一个唯一的复合索引,根据哪个方向查询更多.

真实的故事是什么?复合索引是否会自动有效地索引每一列,以便在其中一列上搜索?最佳(以读取速度,而不是大小)关联表是否应该在每个方向上都有一个复合索引,每列上有一个索引?什么是幕后机制?


编辑:我发现了这个相关的问题,出于某种原因,我在发布之前没有找到它...

推荐答案

(虽然我不确定

是的,可以.但只有前缀:http://use-the-index-luke.com/sql/where-clause/the-equals-operator/concatenated-keys

此外,这个链接也增加了一些困惑

这才是真正需要做的.

一个作为集群索引,另一个作为非集群索引,无论如何都会包含集群索引键——因此无需再次包含该列(thx到JNK).

CREATE CLUSTERED INDEX a on Movies_Actors (fk_movie_id, fk_actor_id);
CREATE NONCLUSTERED INDEX b on Movies_Actors (fk_actor_id);

真实的故事是什么?

http://Use-The-Index-Luke.com/ :)

复合索引会自动生成吗

不,只有索引的前缀.如果你有一个索引(a,b,c),那么查询a=?b=?可以使用索引.然而c=?不能,b=?c=?.

应该是最佳的(在读取速度上,而不是

如果你需要在两个方向上进行连接,可以 Select "是"("每个方向上的综合索引")和"否"("每列上一个").

什么是幕后机制?

好吧,还是同一个链接.

说起SQL Server,您可能最终也会考虑索引视图.这是一种预加入.如上所述,两个索引也可能足够快.

Postgresql相关问答推荐

PostgreSQL数据文件是否仅在判断点期间写入磁盘?

无法在PostgreSQL中创建方案和表

mosquito-go-auth with postgres authorization error

在Ubuntu 18.04 Bionic上安装PostgreSQL(已删除回购)

单个WAL文件中的操作会影响哪些表和多少行

Postgres 使用不同元素数据类型的订单数据

INSERT 语句返回策略违规(USING 表达式)

如何通过 DirectFunctionCall 发送 NULL 参数?

如何在plpgsql中找到一行中的最大值?

OpenShift:如何从我的 PC 连接到 postgresql

等效于 Postgresql 中的 FOUND_ROWS() 函数

Rails 重置所有 Postgres 序列?

从 psycopg2 异常中获取错误消息

如何引用使用 ON CONFLICT 中的函数的唯一索引?

如何在 PostgreSQL 中创建 guid

使用枚举与布尔值?

在同一台机器上创建多个 Postgres 实例

使用 PostgreSQL 的 Linq To Sql

PostgreSQL regexp_replace() 只保留一个空格

PL/pgSQL 中的 BREAK 语句