假设我有一个名为“table”的表,我有3列,a,b和c。
在a,b列上有非聚集索引是什么意思?
列a,b上的非聚簇索引与列b上的非聚簇索引相同吗? (注意顺序)。
此外,列a上的非聚簇索引是否与a上的非聚簇索引相同?
我正在查看网站的sqlserver性能,他们有这些dmv脚本,它会告诉你,如果你有重叠的索引,我相信它是说a上的索引与a,b相同,所以它是多余的。关于索引这是真的吗?
最后一个问题是为什么聚集索引放在主键上。大多数情况下,不会查询主键,因此聚集索引不应位于查询最多的列上。我可能在这里遗漏了一些东西,比如在主键上加速连接?
很好的解释。我应该把它变成一个wiki并更改标题索引解释吗?
答案 0 :(得分:16)
答案 1 :(得分:3)
(a, b)
上的非聚集索引是表格的一部分的“副本”,其行在a
然后在b
上排序包含对原始行的引用。
这样可以帮助您运行查询:
SELECT *
FROM mytable
WHERE a = @A
AND b = @B
,这个:
SELECT *
FROM mytable
ORDER BY
a, b
,这个:
SELECT *
FROM mytable
WHERE a = @A
ORDER BY
b
和其他许多人。
例如,我们有一个这样的表:
# col1 col2 col3
1 1 1 1
2 1 4 8
3 7 2 3
4 3 3 9
5 8 9 4
6 2 2 7
7 5 3 5
8 3 9 4
如果我们在(col2, col3)
上创建索引,它将包含以下数据:
col2 col3 #
1 1 1
2 3 3
2 7 6
3 5 7
3 9 4
4 8 2
9 4 5
9 4 8
,我。即首先在col2
上排序,然后在col3
上排序,然后排在对行的引用上。
很容易看出此索引也是col2
上的索引((col2, col3)
上的排序意味着仅在col2
上排序)。
订单很重要,因此如果我们在(col3, col2)
上创建索引,行的排序方式会有所不同:
col2 col3 #
1 1 1
2 3 3
9 4 5
9 4 8
3 5 7
2 7 6
4 8 2
3 9 4
此索引也是col3
的索引。
如果我们想在(col2, col3)
的某个范围内找到行,我们只需从有序数据中取一个切片:
SELECT col2, col3
FROM mytable
WHERE col2 BETWEEN 2 AND 3
col2 col3 #
1 1 1
----
2 3 3
2 7 6
3 5 7
3 9 4
----
4 8 2
9 4 5
9 4 8
很容易看到我们无法使用此索引在col3
上使用此切片,因为col3
不是自行排序的。
上面提到的“引用”是行的RID
(指向表空间中的位置的指针),如果表本身是非群集的,或者表的簇密钥的值(如果表)是聚集的。
聚集索引不会创建值的卷影副本。相反,它会重新排列表格行本身。
如果您在上面的(col2, col3)
上创建聚簇索引,它只会重新排列表行:
# col1 col2 col3
1 1 1 1
3 7 2 3
6 2 2 7
7 5 3 5
4 3 3 9
2 1 4 8
5 8 9 4
8 3 9 4
因此,群集或非群集是一种存储方法而不是索引。
在Oracle
中,这称为index-organized table
(行已排序),而不是heap-organized table
(行未排序)。
答案 2 :(得分:2)
索引A,B与索引B不同,A
这是因为索引是按特定的排序顺序组织的。因此,假设您需要使用以下WHERE子句进行搜索
WHERE A='somecrit' AND B='SomepartialCrit%' -- notice the wildcard
A,B索引在解析查询时非常有效,但如果是
WHERE A='SomepartialCrit%' AND B='somecrit'
(A,B)指数只能部分帮助(可能比全表扫描更好但不是最佳......),因此(B,A)指数可以拯救......
对于使用包含A和B作为完全匹配(无通配符)的查询的情况,可以以等效方式使用索引(效率方面),尽管一个特定索引的选择可以由其他部分驱动查询,如ORDER BY子句等。
A上的索引与A,C 上的索引不同 对于A,C上的索引可用于解析涉及A和C标准的查询,并且A,C索引也可用于“覆盖”SELECT子句或其部分,即:如果SELECT子句只包括A列和C列(来自这个特定的表),SQL可以提供结果而不必从表中获取数据,它只能从索引中获取A和C值。
“冗余”索引是件坏事吗?
如上所述,额外的索引可以帮助更有效地解决SELECT查询。在不利方面,他们a)使用存储空间和b)使INSERT,UPDATE和DELETE查询效率降低(因为需要在更多地方添加/更改/删除新的/更新/删除的值。
因此,根据可用的可用存储空间和用例(一些大多数只读数据库可以拥有大量索引而不会损害性能,具有频繁插入的数据库)可以看到正确的平衡问题。性能下降太多指数)
关于聚集索引
见Joel Coehoorn的解释 不,给定表的聚簇索引不需要基于主键。选择一个好的聚集索引(或者确实决定不使用聚簇索引)是一个部分科学的部分艺术过程,其范围超出了这个简短的响应。
答案 3 :(得分:2)
列a,b上是非聚集索引 与非聚集索引相同 列b,a? (注意顺序)。
NO!订单很重要。如果你在(a,b)上有一个非聚集索引,你可以使用这个,如果你的WHERE子句对a和b有限制 - 或者它只对a有限制(但不如果只是对b)进行检查。
此外,是非聚集索引 列a与非聚簇相同 索引a,c?
不,不是 - 但如果SQL Server查询优化器在“a”上遇到带有WHERE子句的查询,它将使用此非聚集索引。
马克
答案 4 :(得分:2)
将索引视为电话簿。通常电话簿按姓氏,名字,街道排序。因此,如果你想找到Joe Smith,101 Main Street的电话号码,你打开S for Smith的电话簿,然后你查找Smith下的所有Joes,寻找住在101 Main Street的Joe Smith,然后你找到电话号码。
电话簿的订购方式可以不同,例如街道,名字,姓氏。然后你首先查看Main Street,然后是Joe,最后是Smith。如果你只想找到一个人的号码,那就快了。
如果您想列出居住在主街并且名字为Joe的所有人的电话号码,差异就变得很重要了。对于普通的电话簿,这是一个苦差事:你必须遍历所有的姓氏,找出姓氏的Joes,以及他们是否住在Main Street。要做到这一点,你必须浏览整本电话簿。但是如果索引顺序是street,firstname,lastname,那么任务几乎是微不足道的:查找Main Street,Joe,并复制所有姓氏和他们的电话号码。方式更快。</ p>
此外,如果您只对名称感兴趣,那么电话簿列出街道的事实也无关紧要。如果你想找到所有Joe Smiths的电话号码,你需要一个按姓氏,名字(或名字,姓氏)排序的电话簿。你不在乎电话簿是否所有Joe Smiths都是街上订购的。从这个意义上说,(姓氏,名字,街道)上的索引包含(姓氏,名字)的索引。
所以:index(a,b,c)不等于(c,a,b),如果你有(a,c)你不需要另一个(a)