CRUD操作和JOINS与多个索引的影响是什么?

时间:2011-09-07 18:07:40

标签: sql sql-server sql-server-2008 indexing

我有一个包含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键时如果我们创建一个非集群索引它,这个索引对查询或连接有用吗?

3 个答案:

答案 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)也很重要。

如果你没有这个索引就可以生存,删除它会提高修改的性能,就像删除任何其他索引一样。