索引链接表是否智能?

时间:2015-01-18 19:46:00

标签: mysql database

所以,让我们说例如我有2个表:用户>项目

用户可以拥有最喜欢的项目,而一个项目可以有多个用户将其视为收藏,因此我将使用链接表。

现在我的链接表将包含以下内容:

id (int 11 AI)
user_id (int 11)
item_id (int 11)

现在有必要/有用的是在user_id和item_id上放置一个索引,因为这个表随着时间的推移会包含很多记录。

我不能100%确定何时使用索引。我何时使用它们的想法(可能完全不正确)就是当你拥有大型数据库并且需要在列上搜索/过滤然后对其进行索引时。如果这不正确,我很抱歉,这就是我一直被告知的事情。

2 个答案:

答案 0 :(得分:1)

简而言之,是的。

想象一下,如果每次需要将主键值与另一个表中的外键匹配时DBMS必须在整个表中搜索匹配的键,那么联接的效果如何。

答案 1 :(得分:1)

基本上,是的,这是怎么回事。

在这种情况下,我会说user_id列上的索引会很有用,因为您会向用户显示他们的收藏列表,对吗?

item_id上的索引可能没那么有用,因为我怀疑您是否会显示已经收藏特定项目的用户列表。虽然您可能关心计数(" 100个用户喜欢这个项目"),但您可以添加该索引。或者您可以取消规范化并将计数保留在items表中。这样可以提供更好的性能,尽管您需要编写额外的代码来维护该数字。

最后但并非最不重要 - 在链接表中,您可以取消id列。只需按顺序在两列(user_iditem_id)上添加主键索引。这将确保您无法输入重复的行,并且由于user_id是索引中的第一列,因此您可以在搜索查询中使用它。不再需要在user_id列上添加单独的索引。

但是,这也取决于您使用的代码。如果您正在使用某种需要每个表id列的框架(ORM?),那么这个技巧就没用了。


根据作者的要求,这里有一个关于 索引的快速介绍。

假设您有一个数据库表,它只是一堆行,没有特定的顺序。我们假设我们有一个表people,其中包含namesurnameage列。

现在,当您想要找到John Smith的年龄时,您可能会发出如下查询:

select age from people where name='John' and surname='Smith'

执行此操作时,数据库引擎只能执行一项操作 - 它必须遍历所有行并查找匹配的行。如果有100,000行,则会很慢。

现在有了更快的方法。想想电话簿(经典纸质版)。在它的千页黄页上有数百人的电话号码。然而,即使你是一个人,你也可以很快找到你想要的数字。这是因为数字按名称和姓氏按字母顺序排序。您打开一个随机页面,您可以立即查看您要查找的号码是在您打开的页面之前还是之后。重复几次,你就找到了它。

这种搜索称为"二分搜索"。如果记录按名称和姓氏排序,您的数据库引擎也可以这样做。所以这就是主键 - 它告诉DB不以某种随机顺序存储记录,而是按一些列排序。当新记录出现时,它可以快速找到合适的位置并将其推入那里,从而保持表格永久排序。

这里有几点需要注意。

首先,您可以按一列或多列进行排序,但就像在电话簿中一样,订单很重要。如果您先按name排序,然后按surname排序,那么记录将按顺序排序。这样您就可以快速找到所有记录{{{ 1}}或name='John',但如果您只需查找name='John' and surname='Smith',它根本无法帮助您。就像在电话簿中一样。

其次,在中间某处推动记录也有些缓慢。不是犯罪,但仍然。最后添加记录更快。因此,人们倾向于使用surname='Smith'列作为主键,因为每个新行都将放在最后。

第三,在大多数数据库中,主键不仅用于快速搜索,还用于唯一识别行。这意味着如果有两行具有相同的主键列值,则DB将不满意。在这种情况下,它无法确定哪个必须先行,哪个必须先行,并且它也不是唯一的。使用auto_increment的另一个原因。请注意,如果PK索引中包含多个列,则其组合必须是唯一的 - 每个列都可以是唯一的。在我们的案例中,这意味着可能有许多约翰斯和许多史密斯,但只有一个约翰史密斯。

但我们仍有问题。如果我们想要仅通过auto_incrementname来快速查找行,该怎么办? PK索引只能同时执行其中一项操作。

这是其他非PK指数发挥作用的地方。您可以根据需要添加任意数量的表格。在我们的示例中,我们可以创建另一个索引来仅保留surname列。

当我们这样做时,数据库会创建另一个隐藏表(确定,不是真的,但你可以这样想),它是原始表的副本,但只有surname列和返回原始表中行的特殊链接。此隐藏索引表按surname列排序。因此,当您现在需要通过仅指定surname来查找行时,数据库引擎可以在隐藏索引表中查找它,然后按照链接返回到原始行并从中获取数据。快得多。

这些非PK索引通常也有几种风格。那里有标准的"索引"它没有任何限制 - 你可以在列,空值等中有重复的值。这是一个"唯一的" index,强制索引中的所有值都必须是唯一的;然后有时候会出现像FullText,Spatial等专业索引。索引也往往有一些技术选项,但是你必须阅读数据库的文档。

最后要注意的一件事是 - 索引可以快速查找表中的内容,但是它们需要付出代价。对表的修改(插入,更新,删除)变慢,因为索引也需要更新。记住这一点,只在必要时添加它们。

主键除外。始终添加主键。这是一个订单! :)