如何正确索引多个关联表?

时间:2011-01-17 15:07:27

标签: sql sql-server postgresql many-to-many query-optimization

在这样的典型的许多安排中......

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)
)

但是,这似乎索引只在搜索 {/ em> movie_IDactor_ID时才有用(虽然我不确定复合索引是否也可以正常工作对于各列而言。)

由于“电影X中有哪些演员”和“演员Y在哪些电影中”将成为此表的常见查询,因此每列上应该有一个单独的索引来快速定位演员和电影他们自己。复合索引是否有效地做到了这一点?如果没有,那么在这张桌子上使用复合索引似乎毫无意义。如果复合索引毫无意义,那么如何处理主键呢?候选键显然是两列的复合,但是如果得到的复合索引没有意义(它一定不是?),那似乎是浪费。

此外,this link增加了一些混淆,并表示实际指定两个复合索引甚至可能有用...其中一个为(FK_movie_ID, FK_actor_ID),另一个反向为(FK_actor_ID, FK_movie_ID),其中选择哪个是主键(因此通常是聚类的),而“正好”是一个基于更多查询方向的唯一复合索引。

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


编辑:我发现这个相关的问题,由于某些原因我在发布之前找不到... How to properly index a linking table for many-to-many connection in MySQL?

2 个答案:

答案 0 :(得分:13)

  

(虽然我不确定是否   复合索引也适用于   个别专栏)。

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

  

此外,这个链接增加了一些混乱   并表明它甚至可能   实际指定两个有用   综合指数......其中一个为   (FK_movie_ID,FK_actor_ID)和   其他反向(FK_actor_ID,   FK_movie_ID),

这实际上是要做的事情。

将一个作为聚类索引,另一个作为非聚类索引,无论如何都将包含聚类索引键 - 因此无需再次包含该列(thx到JNK)。

CREATE CLUSTERING INDEX a on Movies_Actors (fk_movie_id, fk_actor_id);
CREATE NONCLUSTERING INDEX b on Movies_Actors (fk_actor_id);
  

真实的故事是什么?

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

  

自动复合索引   有效地索引每列   在一个或另一个上搜索?

没有。只有索引的前缀。如果你有索引(a,b,c),查询a =?和b =?可以使用索引。但是c =?不能,也不能b =?和c =?。

  

应该是最佳的(读取速度,不是   size)关联表有一个   每个方向的综合指数和   每列一个?

如果您需要同时加入两个方向,是(“每个方向的复合索引”)和否(“每列一个”)。

  

什么是幕后机制?

嗯,同样的链接。

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

答案 1 :(得分:2)

在SQL Server中,复合索引只能用于第一列的单个字段搜索。这意味着如果在同一查询中没有FK_actor_id的字段上进行搜索,则FK_Movie_id上应该有一个额外的一个字段索引。