我最近一直在阅读clustered index
和non-clustered index
的工作原理。我用简单的术语理解(如果错误,请纠正我):
支持clustered
和non-clustered index
的数据结构为B-Tree
Clustered Index
:根据索引列(或键)对数据进行物理排序。每clustered Index
只能有一个table
。如果在创建表格期间未指定index
,SQL
服务器将自动在clustered Index
上创建primary key column
。
Q1 :由于数据是根据索引进行物理排序的,因此此处不需要额外的空间。它是否正确?那么当我删除我创建的索引时会发生什么?
Non-clustered Index
:在non-clustered indexes
中,树的leaf-node
包含列值和指向数据库中实际行的指针(行定位器)。这里存在将non-clustered index table
物理存储在磁盘上所需的额外空间。但是,一个不受non-clustered Indexes.
Q2 :这是否意味着对非聚集索引列的查询不会导致排序数据?
Q3 :此处有一个额外的查找,用于使用叶节点处的指针定位实际的行数据。与聚簇索引相比,这会产生多大的性能差异?
锻炼; Tibial:
考虑一个员工表:
CREATE TABLE Employee
(
PersonID int PRIMARY KEY,
Name varchar(255),
age int,
salary int
);
现在我创建了一个员工表(创建了员工的默认聚集索引)。
此表上的两个常见查询仅发生在年龄和工资列上。为简单起见, 假设表格不经常更新
例如:
select * from employee where age > XXX;
select * from employee where salary > XXXX and salary < YYYY;
Q4 :构建索引的最佳方法是什么,以便这两列上的查询具有相似的性能。如果我对年龄段上的年龄查询的聚簇索引会更快,但是在工资列上会更慢。
Q5 :在相关的说明中,我反复看到应该在具有唯一约束的列上创建索引(聚簇和非聚簇)。这是为什么?未能做到这一点会发生什么?
非常感谢你 我读过的帖子在这里:
http://msdn.microsoft.com/en-us/library/ms190457.aspx
What do Clustered and Non clustered index actually mean?
What are the differences between a clustered and a non-clustered index?
答案 0 :(得分:5)
我不知道Microsoft SQL Server的内部,但我可以回答你为你的问题标记的MySQL。其他实现的细节可能会有所不同。
Q1。是的,聚集索引不需要额外的空间。
如果删除聚集索引会发生什么? MySQL的InnoDB引擎始终使用主键(或第一个非空唯一键)作为聚簇索引。如果您定义没有主键的表,或者删除现有表的主键InnoDB generates an internal artificial key for the clustered index。此内部键没有逻辑列来引用它。
Q2。不保证使用非聚集索引的查询返回的行顺序。实际上,它是访问行的顺序。如果您需要按特定顺序返回行,则应在查询中使用ORDER BY
。如果优化器可以推断出您所需的顺序与访问行的顺序(索引顺序,无论是通过聚簇索引还是非聚集索引)相同,那么它可以跳过排序步骤。
Q3。 InnoDB非聚集索引没有指向索引叶子上相应行的指针,它具有主键的值。因此,非聚集索引中的查找实际上是两个B树搜索,第一个是查找非聚集索引的叶子,然后是聚簇索引中的第二个搜索。
这是单个B树搜索(或多或少)的两倍,因此InnoDB有一个名为Adaptive Hash Index的额外功能。经常搜索的值会缓存在AHI中,并且下次查询搜索缓存值时,它可以执行O(1)查找。在AHI缓存中,它找到一个直接指向聚簇索引的叶子的指针,因此它在一部分时间内消除了两个 B树搜索。
这可以提高总体性能取决于您搜索之前搜索过的相同值的频率。根据我的经验,哈希搜索与非哈希搜索的比率通常约为1:2。
Q4。构建索引以提供您需要优化的查询。通常,聚簇索引是主键或唯一键,至少在InnoDB的情况下,这是必需的。 age
和salary
都不可能是唯一的。
您可能会喜欢我的演示文稿How to Design Indexes, Really。
Q5。当您声明唯一约束时,InnoDB会自动创建索引。如果没有为其存在索引,则不能拥有约束。如果您没有索引,那么在插入值时引擎如何确保唯一性?它需要在整个表中搜索该列中的重复值。该索引有助于使独特的检查更加有效。
答案 1 :(得分:3)
对于SQL Server
Q1 只有聚集索引不是唯一的,才需要额外的空间。 SQL Server将在内部向非唯一聚簇索引添加一个4字节的uniquifier。这是因为它使用群集密钥作为非聚集索引中的rowid。
Q2 可以按顺序读取非聚集索引。这可能有助于您指定订单的查询。它也可能使合并连接具有吸引力。它还有助于范围查询(x&lt; col和y&gt; col)。
Q3 SQL Server执行额外的&#34;书签查找&#34;使用非聚集索引时。但是,只有当它需要一个不在索引中的列时。另请注意,您可以在索引的叶级别中添加include
个额外列。如果可以在没有附加查找的情况下使用索引,则将其称为覆盖索引。
如果需要书签查找,则不会占用很高比例的行,直到扫描整个聚簇索引更快。级别取决于行大小,密钥大小等。但行的5%是典型的截止。
Q4 如果您的应用中最重要的事情是尽可能快地完成这两个查询,您可以在这两个查询上创建覆盖索引:
create index IX_1 on employee (age) include (name, salary);
create index IX_2 on employee (salary) include (name, age);
请注意,您不必专门包含群集密钥,因为非群集索引将其作为行指针。
Q5 由于uniquifier,这对于群集密钥比非群集密钥更重要。但真正的问题是索引是否对您的查询具有选择性。想象一下bit
值的索引。除非数据分布非常偏斜,否则这样的索引不可能用于任何事情。
有关uniquifier的更多信息。想象一下你和一个关于年龄的非唯一聚集索引,以及一个关于薪水的非聚集索引。假设您有以下行:
age | salary | uniqifier
20 | 1000 | 1
20 | 2000 | 2
然后工资指数会找到像这样的行
1000 -> 20, 1
2000 -> 20, 2
假设您运行了查询select * from employee where salary = 1000
,并且优化器选择使用工资索引。然后它会从索引查找中找到对(20,1),然后在主数据中查找该值。