SQL Server索引使用问题

时间:2009-08-10 05:05:00

标签: sql-server performance query-optimization

假设如下:

/*

drop index ix_vouchers_nacsz on dbo.vouchers;
drop index ix_vouchers_nacsz2 on dbo.vouchers;

create index ix_vouchers_nacsz on dbo.Vouchers(
    FirstName, LastName,
    Address, Address2, City,
    State, Zip, Email
);

create index ix_vouchers_nacsz2 on dbo.Vouchers(
    Email, FirstName, LastName,
    Address, Address2, City,
    State, Zip
);

*/

select count(firstname) from vouchers
    with (index(ix_vouchers_nacsz))
where 
    firstname = 'chris' and
    lastname = '' and
    address = '' and
    address2 = '' and
    city = '' and
    state = '' and
    zip = ''

select count(firstname) from vouchers
    with (index(ix_vouchers_nacsz2))
where 
    firstname = 'chris' and
    lastname = '' and
    address = '' and
    address2 = '' and
    city = '' and
    state = '' and
    zip = ''

为什么第二个索引会导致索引扫描,而第一个索引会导致索引搜索?键的顺序有什么不同?

3 个答案:

答案 0 :(得分:5)

第二个索引以电子邮件字段开头,但您没有过滤电子邮件。这使得索引无用。

索引通常为b-tree,允许您执行binary search。 b树按其索引字段排序。因此,如果您知道第一个字段,则可以快速查找。在第一个字段的相同值内,您可以非常快速地查找第二个字段。

这就像一本按姓氏排序的电话簿。您无法使用它来搜索特定的电话号码。

答案 1 :(得分:0)

应用“电话簿”类比可能有助于理解。

第一个索引是一个'电话簿',按FirstName排序,然后是姓氏,依此类推。 如果你被要求在这本电话簿中查找克里斯,那么你可以找到索引所列的所有克里斯。

在第二个索引中,是一个电话簿按“电话号码”排序(或电子邮件一样容易),然后是名字,然后是姓氏等。 如果您要求使用此电话簿查找带有Chris姓名的列表,那么您的运气不好,电话簿就不会那样排序!当然,如果您被要求查找电子邮件地址example@example.com并命名为Chris,那么您可以先找到该电子邮件地址,然后查找匹配的名称。

答案 2 :(得分:0)

在索引“索引中的列排序”的情况下,“where子句中的列排序”将会遇到很多。你可以参考以下链接:

http://ashishkhandelwal.arkutil.com/sql-server/quick-and-short-database-indexes/

•使用索引的最佳实践  •如何获得最佳性能表单索引  •聚集索引注意事项  •非聚集索引注意事项

我确信这会在规划索引时帮助您。