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
列,那么您可以在电子邮件上添加索引,这将导致访问电子邮件的查询更快。
但是,添加不必要的索引也有不利之处,因此请仅在确实比其他列需要访问更多的列上添加它。例如,UPDATE
、DELETE
和 INSERT
的查询速度会随着您拥有的索引越多越慢,因为 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)) 时间,而不是扫描整个表。
一般来说,大表中经常在WHERE
、ORDER BY
或(尤其是)JOIN
子句中使用的任何列都应该有一个索引。由于需要为每一个INSERT
、UPDATE
或DELETE
更新索引,因此会减慢这些操作的速度。如果你写的很少,读的很多,那么索引到你听到的内容。如果您有大量写入和大量查询,需要在许多列上建立索引,那么您就有大问题了。
【讨论】:
【参考方案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 到底是做啥的?