内部联接的索引与where子句

Sup*_*oss 4 sql-server indexing join

如果我有以下查询:

select some cols 
   from tbl_a
INNER JOIN tbl_b ON tbl_a.orderNumber = tbl_b.orderNumber
   where tlb_b.status = 'XX'
Run Code Online (Sandbox Code Playgroud)

假设两个表只有订单号上的聚簇索引,从性能角度来看,扩展表b上的聚簇索引以包括where子句中引用的状态列会更好吗?

Rem*_*anu 7

  1. 你扩展tbl_b以在orderNumber 之后添加状态:create clustered index ... on tbl_b(orderNumber, status).对于上面的查询,没有明显的区别.该计划仍然必须端到端扫描tbl_b并匹配tbl_a中的每个订单号(可能是合并连接).

  2. 您可以扩展tbl_b以在orderNumber 之前添加状态:create clustered index ... on tbl_b (status, orderNumber).现在有一个巨大的差异.该计划可以在tbl_b上进行范围扫描,仅使用状态'xx'进行范围扫描,并且仅使用嵌套循环连接匹配对应orderNumber的tbl_a.

放置一个低选择性列(通常是'status')作为索引中最左边的键通常是一件好事.在"聚集索引"中最左边的列创建"状态"行通常也是一件好事,因为它将具有相同状态的记录物理地组合在一起.请注意,这样做会对所有查询产生影响.如果没有指定status,你也会通过orderNumber松开直接访问,你必须单独在orderNumber上添加一个非聚集索引来覆盖它(通常是PK非聚集索引).

我知道你的实际数据基数和选择性,我做了所有这些评论.如果tbl_a和tbl_b的基数非常偏差,那么事情可能会有所不同.例如.如果tbl_a有10个记录,其中包含10个不同的订单号,而tbl_b有10M记录,其中10M订单号超过我的建议,则选项2将没什么区别,因为该计划将始终选择tbl_a扫描tbl_b中的搜索范围查找10次.