我在SQL Server 2005中有一个大表,我必须通过非群集密钥选择记录,并且我正在尽力优化此过程。
该表有很多列,我在三个不同的列上添加了非聚集索引。
SELECT * FROM table WHERE Field1 = 10;
SELECT * FROM table WHERE Field2 = 40;
SELECT * FROM table WHERE Field3 = 'A';
Field1和Field2是整数字段,Field3是varchar。
当我从SQL Server请求这三个查询的估计查询执行计划时,我基本上得到了相同的计划:
SELECT -> Nested Loop -> Index Seek
-> Key Lookup
但我发现执行时间非常不一致。具体来说,第二个查询占总查询成本的98%。它的执行计划与其他计划相同,只是Key Chaup步骤与Index Seek相比成本为100%。在另外两个查询中,它接近50%。
我知道密钥查找是不可取的,可以通过向索引添加列来避免,这样就不需要查找额外的列。但是,在这种情况下,我希望将表中的所有列都返回给我,因此将它们全部添加到索引中是没有意义的。但是,一个索引如何导致Key Lookup操作比另一个Key Lookup花费的时间更长?
答案 0 :(得分:2)
成本不一定与时间有关,而是与资源消耗更密切相关。如果没有查看查询,知道表结构以及列中包含的数据组成,很难说你的案例中发生了什么。但是,根据您的标准匹配的记录数量可能会使不同查询计划的成本产生差异。
关于表的索引,如果您可以在索引中包含尽可能多的条件列,那么您可能会更好。根据您的数据,您可以通过索引最具选择性的列(最有可能消除大部分数据的列)来获得更好的提升。 (但情况并非如此,特别是如果您与其他表联接,对结果进行排序等)。您可以根据需要添加其他列或有益。您可以在创建索引时使用“include”子句,为索引添加选择性较低的“where”列,以减少所需的关键查找次数。
答案 1 :(得分:1)
但是一个索引怎么能导致一个Key 查找操作需要这么多 比另一个Key Lookup更长?
这完全取决于预期密钥长度的当前统计数据。
查询优化器(QO)
通过查看索引的统计信息来工作。 fieldb上的索引的平均基数可以为100,而其他字段的索引的平均基数为10000(特定的100倍)。因此,它会根据averaged
计划为您提供相对指示。
要查看具体信息,请始终启用统计信息*,但这实际上只会为您提供actual execution time
个特定值。在某些方面,如果访问变量是随机的,QO在长期内可以更准确。
考虑这两个查询的案例
SELECT * FROM table WHERE Field2 = 40;
SELECT * FROM table WHERE Field2 = 42;
假设假设42是一个特殊代码,在所有记录的80%中使用。 40是仅在1个记录中使用的唯一代码。您不能指望QO每个都显示不同的估计行数?然而,如果您运行查询,除非涉及参数化/计划缓存,否则第二个可能会使用clustered index
扫描表而不是执行80%(昂贵的)书签查找。
*启用统计报告
set statistics io on
set statistics time on
答案 2 :(得分:0)
我见过几个案例,其中“查询成本(相对于批次)”百分比可能会误导至少。
最好结合io和时间统计来查看实际执行计划,以了解实际发生的情况。
set statistics io on
set statistics time on
SELECT * FROM table WHERE Field1 = 10;
SELECT * FROM table WHERE Field2 = 40;
SELECT * FROM table WHERE Field3 = 'A';
然后查看每个查询返回的逻辑读取,CPU时间和已用时间。