我有一个包含120列的表格。它上面有8个索引(1个聚簇,7个非聚簇)。作为测试,我在表中插入了3,400行,平均花费了12秒。
我使用不同的名称创建了相同的表,并在其上创建了32个附加索引(共40个索引)并再次插入相同的3,400行,平均花费了13.5秒。
我在创建索引之前读过,创建了表的副本,并按参与索引的列进行排序。
我有两个问题:
1)对于每个索引,是否都创建了表的副本?
2)32个索引仅为同一INSERT
命令添加1.5秒。这个平均值是否仍然保持10,000行?或80个索引?
我有另一个问题:
3)当我们在列上有一个外键时,SQL Server会自动在其上创建非集群索引。当我们在列上有一个forein键时如果我们创建一个非集群索引它,这个索引对查询或连接有用吗?
答案 0 :(得分:3)
1)op问:Is it true that by every index a copy of table created?
这不是真的。索引会将索引列和指针存储回行(如聚簇PK等)。它还将存储任何INCLUDE列,但这是另一个主题。
2)很难猜测不知道硬件,表格或索引的时间。我确信SQL Server擅长优化索引的维护。你应该通过插入只有PK的相同行来测试这个,然后再用40个索引重试,然后再用80重新测试。我确信大部分时间只是插入。
编辑
3)op询问when we have a Foreign key on a column SQL Server automatically create non-cluster index on it.this Index useful for quering or Joins?
SQL Server不会自动为外键创建索引。但是,在FK列上添加索引可能很有用。如果编写一个在FK上连接两个表的查询,则可以使用索引。请考虑以下事项:
tableA
RowID int PK
RowDate datetime
OtherID int
tableB
OtherID int PK
someValue varchar(5)
如果您将tableA.OtherID的FK添加到tbaleB.OtherID并使用此查询:
select * from tableA a INNER JOIN tableB b ON a.OtherID=b.OtherID
WHERE a.RowDate<'2011/1/1'
然后将不使用tableA.OtherID上的索引,将使用tableA.RowDate上的索引,并将使用tableB.OtherID上的PK索引。
select * from tableA a INNER JOIN tableB b ON a.OtherID=b.OtherID
WHERE b.someValue='AA'
could also be written as:
select * from tableb b INNER JOIN tableA b ON b.OtherID=a.OtherID
WHERE b.someValue='AA'
然后可以使用tableA.OtherID上的索引,并且将使用tableb.someValue上的任何索引。
答案 1 :(得分:2)
1)是否为每个索引创建了表的副本?
没有。每个索引都会创建一个数据结构,例如btree或hash表,其中包含指向表的指针。每行一个指针。它们在磁盘空间方面相当便宜。
2)32个索引仅为同一个INSERT命令添加1.5秒。做这个 平均值为10,000行?或80个索引?
你必须对它进行基准测试才能确定,但最有可能的是,是的。索引通常以线性方式扩展。
答案 2 :(得分:1)
1)对于每个索引,是否都创建了表的副本?
部分。由特定(非聚集)索引索引的列将“复制”到索引数据结构(通常是B树),但其余列不会。顺便说一句,一些RDMBS支持一种索引压缩形式(例如Oracle,不确定MS SQL Server),这可能会显着“缩小”低选择性索引的占用空间。
对于聚簇索引,表和索引实际上是相同的数据结构。因此,如果你只拥有一个索引(即只是一个主键),那么与非聚集索引获得的经典B树/表堆组合相比,使其聚类通常会降低所需的空间。
但,群集索引会增加所有其他(即非群集)索引的“复制”。来自MSDN:
“聚簇索引的键值被所有非聚簇索引用作查找键,因此存储在每个非聚簇索引叶条目中。”
如果你无法逃脱拥有多个索引,至少要摆脱群集并只使用非聚集索引。
2)32个索引仅为同一个INSERT命令添加1.5秒。这个平均值是否仍然保持10,000行?或80个索引?
只有3,400行(或者说是10,000行),我怀疑你仍然处于缓存范围之内,这可能会掩盖你可能为更大的数据集维护所有这些索引的性能问题。与往常一样,在您实际使用具有代表性的数据量进行基准测试之前,您无法确定...
3)当我们在列上有一个外键时,SQL Server会自动在其上创建非群集索引。这个索引对查询或连接有用吗?
根据特定查询的构造方式,它可能会也可能不会提高性能。它对级联参照完整性(ON DELETE / UPDATE CASCADE)也很重要。
如果你没有这个索引就可以生存,删除它会提高修改的性能,就像删除任何其他索引一样。