我正在使用SQL 2000,我在一个包含大约3000万行的表上运行一个简单的select语句。选择查询如下所示:
select col1, col2, col3 from Table1 where col4=@col4 and col5=@col5 and col6=@col6
该表中有一个聚簇索引(即一个主键),但是没有用作where标准。上面提到的所有标准都没有编入索引。
如何优化此查询?
如果我在where子句中为每列添加索引,那会有什么不同吗?
如果我在where子句中有10列,那么这10列中的所有列都应该包含索引吗?
编辑:这可能是最常见的面试问题之一:)
答案 0 :(得分:5)
是的,它会带来巨大的变化。
您应该添加一个包含三个字段的索引,而不是为每个字段添加一个索引。 (当然,这在实践中如何使用取决于字段的独特性以及您将在桌面上使用的其他查询。)
请注意,当您在表中插入或删除记录或更新记录的索引字段时,添加索引也会产生很小的负面影响。
答案 1 :(得分:4)
如何优化此查询?
您可以制作覆盖索引:
CREATE INDEX ix_table1_456__123 ON table1 (col4, col5, col6) INCLUDE (col1, col2, col3)
,查询甚至不必进行表查找。
如果我在where子句中为每列添加索引,那会有什么不同吗?
与没有索引相比,这很可能会改善查询,但创建带覆盖的复合索引最有可能更好。
但是,如果每个列都具有高基数(即UNIQUE
或接近它),那么与复合索引相比,创建单个索引甚至可以改善查询。
如果某些列的大小较大(如VARCHAR(400)
)而另一列较小的列具有较高的基数,则尤其如此。
如果我在where子句中有10列,那么这10列中的所有列都应该包含索引吗?
如果你有10
列,就像我上面所说的那样,在增加的密钥大小(降低性能)和提高选择性之间进行权衡。
如果首先3
列是唯一的或几乎唯一的,那么添加其他列不会增加选择性,但会增加密钥大小。
索引的大小会越来越大,需要额外的时间来搜索它。
如果10
列提供足够高的选择性,则不应在所有3
列上创建索引,因为遍历较大的索引将比读取一些额外的键更昂贵。
您可能希望在我的博客中阅读这篇文章:
答案 2 :(得分:2)
如果我为每列添加索引 那个子句,会是什么 差?
是的,添加索引会产生巨大的性能差异。这是以索引占用大量磁盘空间为代价的,并且对INSERT和UPDATE命令的影响非常小。
如果我在where子句中有10列, 应该是所有这10列都有 它们中的索引?
情况并非总是如此。如果我们将您提供的SQL查询作为示例,并且仅在col4上创建索引,则select * from Table1 where col4=@col4
可能只返回几条记录。在这种情况下,在col5和col6上使用索引不会获得太多收益,因为数据库引擎只需扫描返回col4=@col4
的少数记录。
因此,正如您所看到的,这在很大程度上取决于您要存储的数据类型。此外,索引在任何具有低基数的列上也可能没有多大用处:即具有很少唯一值的列。
答案 3 :(得分:2)
标准中哪一列最具选择性?在该列上创建索引会最大程度地影响性能。 是否应将另一列添加到相同的索引,取决于选择性。您需要检查查询计划以找出它:)