sql—如何正确创建非聚集索引以帮助存储过程

w6mmgewl  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(316)

我正在sql server中准备一个存储过程。基本上,我这里有两个表,表a和表b,这两个表是连接在一起的 Col4 . 这个存储过程将根据表b中的属性过滤表a,比如 Col41 以及 Col42where 条款(两者) Col41 以及 Col42 属于 float 数据类型)。
表a:

Col1    Col2    Col3    Col4
Row1  **  **  **  **
Row2  **  **  **  **

表b:

Col5    Col4    Col41   Col42
Row1  **  **  **  **
Row2  **  **  **  **

这两个表中有很多记录,因此我计划使用非聚集索引来帮助查询(两个表都将其第一列设置为主键)。
当我如下图所示创建了这个非聚集索引,然后在存储过程(临时索引)中使用后将其丢弃时,性能非常好。

CREATE NONCLUSTERED INDEX IX_1 ON tableB (Col41, Col42)

DROP INDEX IF EXISTS IX_1 ON tableB

但是,如果我直接将相同的非聚集索引添加到tableb(永久索引),或者右键单击tableb的index文件夹,或者运行下面的代码,性能会差得多。似乎即使创建了非聚集索引,也没有使用它。

CREATE NONCLUSTERED INDEX IX_1 ON tableB (Col41, Col42)

不明白为什么运行结果是这样的。有人能告诉我怎么解决这个问题吗?谢谢。

nuypyhwy

nuypyhwy1#

对于你的情况,你需要两个索引-

tableB(Col41, Col42)
tableA(Col4)

如果您仍然看到问题,如alwayslearning所述,请检查执行计划,它可以告诉您如何访问数据的详细信息。

2o7dmzc5

2o7dmzc52#

正如@mitch-wheat提到的,添加索引并不能确保它总是被使用。还有一件事,不要在存储过程中创建和删除索引,除非是在临时表上创建索引。创建索引是一项代价高昂的操作。最好在开发代码之外单独做。
这取决于具体查询的查询和索引的选择性。有一种称为“临界点”的方法,它将检查使用索引还是直接从表中读取对特定查询都有好处。阅读更多关于引爆点金伯利特里普
关于您的查询,当您告诉col41和col42总是要用于filter,并且要使用col4连接tablea时,我建议您像下面那样覆盖索引,以使索引可查找。如果组合是唯一的,请创建唯一索引。

CREATE NONCLUSTERED INDEX Idx_TableB_Col41_Col42_Col4 ON TableB(Col41,Col42,Col4)

但是,这里您必须看到列的选择性,才能看到列的顺序:col41和col42。选择度较高的列位于左侧,选择度较低的列位于右侧。
要查找列的选择性,请参阅列统计信息。将有第二个结果集,它告诉列的密度。它越小,柱的选择性就越强。

EXEC DBCC SHOW_STATISTICS(TableB, ColumnStatisticsName)

另外,在tablea上为col4创建索引。如果列是唯一的,请创建唯一索引。

CREATE NONCLUSTERED INDEX Idx_TableA_col4 ON TableA(Col4)

注意:以上也不能保证索引总是被使用。如果看不到执行计划和实际查询,很难判断。上述准则也专门针对一个查询。我建议您看看,是否可以将上述索引与现有查询合并到其他索引,以减少表上的索引占用。

相关问题