所以,让我们说例如我有2个表:用户>项目
用户可以拥有最喜欢的项目,而一个项目可以有多个用户将其视为收藏,因此我将使用链接表。
现在我的链接表将包含以下内容:
id (int 11 AI)
user_id (int 11)
item_id (int 11)
现在有必要/有用的是在user_id和item_id上放置一个索引,因为这个表随着时间的推移会包含很多记录。
我不能100%确定何时使用索引。我何时使用它们的想法(可能完全不正确)就是当你拥有大型数据库并且需要在列上搜索/过滤然后对其进行索引时。如果这不正确,我很抱歉,这就是我一直被告知的事情。
答案 0 :(得分:1)
简而言之,是的。
想象一下,如果每次需要将主键值与另一个表中的外键匹配时DBMS必须在整个表中搜索匹配的键,那么联接的效果如何。
答案 1 :(得分:1)
基本上,是的,这是怎么回事。
在这种情况下,我会说user_id
列上的索引会很有用,因为您会向用户显示他们的收藏列表,对吗?
item_id
上的索引可能没那么有用,因为我怀疑您是否会显示已经收藏特定项目的用户列表。虽然您可能关心计数(" 100个用户喜欢这个项目"),但您可以添加该索引。或者您可以取消规范化并将计数保留在items
表中。这样可以提供更好的性能,尽管您需要编写额外的代码来维护该数字。
最后但并非最不重要 - 在链接表中,您可以取消id
列。只需按顺序在两列(user_id
和item_id
)上添加主键索引。这将确保您无法输入重复的行,并且由于user_id
是索引中的第一列,因此您可以在搜索查询中使用它。不再需要在user_id
列上添加单独的索引。
但是,这也取决于您使用的代码。如果您正在使用某种需要每个表id
列的框架(ORM?),那么这个技巧就没用了。
根据作者的要求,这里有一个关于 索引的快速介绍。
假设您有一个数据库表,它只是一堆行,没有特定的顺序。我们假设我们有一个表people
,其中包含name
,surname
,age
列。
现在,当您想要找到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_increment
和name
来快速查找行,该怎么办? PK索引只能同时执行其中一项操作。
这是其他非PK指数发挥作用的地方。您可以根据需要添加任意数量的表格。在我们的示例中,我们可以创建另一个索引来仅保留surname
列。
当我们这样做时,数据库会创建另一个隐藏表(确定,不是真的,但你可以这样想),它是原始表的副本,但只有surname
列和返回原始表中行的特殊链接。此隐藏索引表按surname
列排序。因此,当您现在需要通过仅指定surname
来查找行时,数据库引擎可以在隐藏索引表中查找它,然后按照链接返回到原始行并从中获取数据。快得多。
这些非PK索引通常也有几种风格。那里有标准的"索引"它没有任何限制 - 你可以在列,空值等中有重复的值。这是一个"唯一的" index,强制索引中的所有值都必须是唯一的;然后有时候会出现像FullText,Spatial等专业索引。索引也往往有一些技术选项,但是你必须阅读数据库的文档。
最后要注意的一件事是 - 索引可以快速查找表中的内容,但是它们需要付出代价。对表的修改(插入,更新,删除)变慢,因为索引也需要更新。记住这一点,只在必要时添加它们。
主键除外。始终添加主键。这是一个订单! :)