如果我有以下查询:
select some cols
from tbl_a
INNER JOIN tbl_b ON tbl_a.orderNumber = tbl_b.orderNumber
where tlb_b.status = 'XX'
假设两个表都仅在订单号上有聚集索引,从性能角度来看,扩展表 b 上的聚集索引以包含 where 子句中引用的状态列会更好吗?
最佳答案
您扩展 tbl_b 以在 orderNumber之后添加状态:
在 tbl_b(orderNumber, status) 上创建聚集索引 ...
。对于上面的查询,不会有明显的差异。该计划仍然必须端到端扫描 tbl_b 并匹配 tbl_a 中的每个订单号(可能是合并连接)。您扩展 tbl_b 以在 orderNumber之前添加状态:
在 tbl_b (status, orderNumber) 上创建聚集索引 ...
。现在有一个巨大的差异。该计划可以使用嵌套循环连接对 tbl_b 进行范围扫描,以仅获取状态为“xx”的那些,并且仅匹配 tbl_a 的相应 orderNumber。
将低选择性列(通常是“状态”)放置为索引中最左边的键通常是一件好事。将像“status”这样的行设置为聚集索引中最左边的列通常也是一件好事,因为它将具有相同状态的记录物理地分组在一起。请注意,这样做将对所有查询产生影响。如果未指定状态,您还会失去对 orderNumber 的直接访问,您必须单独在 orderNumber 上添加非聚集索引来覆盖它(通常是 PK 非聚集索引)。
我在不知道您的实际数据基数和选择性的情况下发表了所有这些评论。如果 tbl_a 和 tbl_b 的基数非常倾斜,那么情况可能会有所不同。例如。如果 tbl_a 有 10 条记录,有 10 个不同的订单号,而 tbl_b 有 10M 条记录,有 10M 订单号,那么我的建议是选项 2. 几乎没有什么区别,因为该计划总是选择扫描 tbl_a,在 tbl_b 中进行搜索范围查找 10 次。
关于sql-server - 带有 where 子句的内连接索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2002321/