SQL:主键和索引到底是做啥的?

Posted

技术标签:

【中文标题】SQL:主键和索引到底是做啥的?【英文标题】:SQL: what exactly do Primary Keys and Indexes do?SQL:主键和索引到底是做什么的? 【发布时间】:2010-11-21 21:02:41 【问题描述】:

我最近开始开发我的第一个使用 SQL 数据库的严肃应用程序,并且我正在使用 phpMyAdmin 来设置表。有几个可选的“功能”我可以给出不同的列,但我不完全确定它们的作用:

主键 索引

我知道 PK 的用途以及如何使用它,但我想我的问题是为什么需要一个 - 除了事实之外,它与仅将列设置为“唯一”有何不同那你只能有一个PK?只是为了让程序员知道这个值唯一标识了记录吗?还是它也有一些特殊的属性?

我不知道“索引”的作用——事实上,我见过它使用的唯一一次是(1)我的主键似乎被索引了,(2)我听说索引在某种程度上是与性能有关;你想要索引列,但不要太多。如何决定要索引哪些列,它到底是做什么的?

编辑:一个索引列应该是一个可能想要排序的列吗?

非常感谢,

马拉

【问题讨论】:

【参考方案1】:

主键通常用于为您的记录创建一个数字“id”,并且此 id 列会自动递增。

例如,如果您有一个带有 id 字段的 books 表,其中 id 是主键并且也设置为 auto_increment(在 phpmyadmin 中的“Extra”下),那么当您第一次向表中添加一本书,其 id 将变为 1'。下一本书的 id 将自动为“2”,依此类推。通常,每个表都应至少有一个主键,以帮助轻松识别和查找记录。

当您需要定期从表中检索某些信息时,会使用索引。例如,如果您有一个users 表,并且您将需要经常访问email 列,那么您可以在电子邮件上添加索引,这将导致访问电子邮件的查询更快。

但是,添加不必要的索引也有不利之处,因此请仅在确实比其他列需要访问更多的列上添加它。例如,UPDATEDELETEINSERT 的查询速度会随着您拥有的索引越多越慢,因为 mysql 需要为每个索引列存储额外的信息。更多信息可以在this page找到。

编辑:是的,ORDER BY 中经常需要使用的列应该有索引,WHERE 中使用的列也应该有索引。

【讨论】:

谢谢您,您的帮助很大!不过我想知道,将列设置为 PK 与将列设置为 auto_increments 的唯一整数有什么不同?它在引擎盖下还有其他作用吗? 我已经编辑回答您关于索引缺点的问题。主键也可用作索引,因此当您在列上有 PK 时,所有基于该 id 的 SELECT 或 ORDER BY 查询都会更快。此外,将确保每个 'id' 都是唯一的,因此如果您只有一个正在更新的 INT 列,您将不会有重复的 ID。 主键不必是数字或单个字段。和 IDENTITY 列将更适合该描述。相反,主键用于告诉 RDBMS 指定字段可以唯一标识表中的单个行。本质上是一个唯一的索引。主键也是数据存储顺序的控制因素(SQLServer 中的集群主键)是正常的(但不是必需的),因此显着缩短了查找数据行所需的时间(用于读取、写入等) 索引为信息创建了一个搜索树,因此将一个表的搜索复杂度从 O(n) 降低到 O(log n)。使用连接表可以进一步降低复杂性。【参考方案2】:

主键基本上是一个唯一的索引列,充当该表中行的“官方”ID。最重要的是,它通常用于外键关系,即如果另一个表首先引用了一行,它将包含该行主键的副本。

请注意,可以有一个复合主键,即一个包含多于一列的主键。

索引可以缩短查找时间。它们通常是基于树的,因此通过索引查找特定行需要 O(log(n)) 时间,而不是扫描整个表。

一般来说,大表中经常在WHEREORDER BY 或(尤其是)JOIN 子句中使用的任何列都应该有一个索引。由于需要为每一个INSERTUPDATEDELETE 更新索引,因此会减慢这些操作的速度。如果你写的很少,读的很多,那么索引到你听到的内容。如果您有大量写入和大量查询,需要在许多列上建立索引,那么您就有大问题了。

【讨论】:

【参考方案3】:

主键和唯一键的区别最好通过一个例子来解释。

我们有一个用户表:

USER_ID number 
NAME varchar(30)
EMAIL varchar(50)

在该表中,USER_ID 是主键。 NAME 并不是唯一的——世界上有很多 John Smiths 和 Muhammed Khans。 EMAIL 必须是唯一的,否则全球电子邮件系统将无法工作。所以我们对 EMAIL 设置了一个唯一的约束。

那么为什么我们需要一个单独的主键呢?三个原因:

    数字键更高效 在外键中使用时 关系,因为它占用更少的空间 电子邮件可以更改(例如 交换提供者),但用户是 还是一样;涟漪变化 整个架构中的主键值 总是一场噩梦 使用它总是一个坏主意 敏感或私人信息 外键

【讨论】:

【参考方案4】:

在关系模型中,保证在表中存在且唯一的任何列或列集都可以称为表的候选键。 “现在”的意思是“不为空”。数据库设计中的常见做法是将其中一个候选键指定为主键,并使用对主键的引用来引用整行或该行描述的主题项。

在 SQL 中,PRIMARY KEY 约束相当于每个主键列的 NOT NULL 约束,以及所有主键列的 UNIQUE 约束。在实践中,许多主键被证明是单列。

对于大多数 DBMS 产品,PRIMARY KEY 约束也会导致在主键列上自动构建索引。当为主键创建新条目时,这会加速系统检查活动,以确保新值不会与现有值重复。它还加快了基于主键值的查找速度,并在主键和引用它的外键之间进行连接。加快多少取决于查询优化器的工作方式。

最初,关系数据库设计人员在数据中寻找给定的自然键。近年来,趋势是总是创建一个称为 ID 的列,一个整数作为第一列,每个表的主键。 DBMS 的自动生成功能用于确保此密钥是唯一的。这种趋势记录在“奥斯陆设计标准”中。它不一定是关系设计,但它服务于遵循它的人的一些直接需求。我不推荐这种做法,但我知道这是一种普遍做法。

索引是一种数据结构,它允许根据对被索引的表列的描述快速访问表中的几行。索引由某些表列的副本组成,称为索引键,其中散布着指向表行的指针。指针通常对 DBMS 用户隐藏。索引与查询优化器协同工作。用户在 SQL 中指定正在寻找的数据,优化器提出索引策略和其他策略,用于将正在寻找的内容转换为找到它的策略。有某种组织原则,例如排序或散列,使索引能够用于快速查找和某些其他用途。一旦数据库构建器创建了索引或声明了主键,这一切都是 DBMS 内部的。

可以建立与主键无关的索引。主键可以在没有索引的情况下存在,尽管这通常是一个非常糟糕的主意。

【讨论】:

(如果你还在的话)= 我很好奇你为什么不建议将整数列设置为主键。我已经在我的 SQL 开发中将此作为常规实践,并发现它使 PHP 脚本中的选择、更新、插入和删除(以及建立表之间的关系和创建连接)比依赖于从数据。

以上是关于SQL:主键和索引到底是做啥的?的主要内容,如果未能解决你的问题,请参考以下文章

FragmentManager 和 FragmentTransaction 到底是做啥的?

“del”到底是做啥的?

selenium 中的 ime() 到底是做啥的?

DrawShadow 中的 Elevation 到底是做啥的?

.join() 方法到底是做啥的?

.join() 方法到底是做啥的?