SQL Server何时选择索引扫描?

时间:2012-03-30 08:17:06

标签: sql sql-server sql-server-2005

select 
    a.Transport_Mode, sum(a.Inv_Qty)
from 
    dbo.DespSum_Year a, dbo.Item_Master b
where 
    a.Inv_Date between '2011-04-01' and '2012-03-31'
    and a.item_name = b.itemcode
group by 
    a.Transport_Mode

我在despsum_year中有1000万行,在Inv_date上有非聚集索引。

当我运行上面的查询时,它使用表扫描显示它。谁能告诉我如何使用索引扫描进行查询?

2 个答案:

答案 0 :(得分:2)

您的查询有三个部分需要排序表 1. JOIN
2. WHERE条款
3. GROUP BY

您的查询未使用索引,因为其他人被认为更重要。将索引放在其他字段上,并在适当的位置合并索引。

我会提供更多详细信息,但不幸的是,您的查询并未说明哪个字段属于哪个表。有关详细信息,请提供每个表的架构和索引的 完整 详细信息。

另外,了解更多的数据行为会很好:通过Transport_Mode进行挖掘可以给出几个大组还是许多小组? item_name / itemcode是一个表中的唯一键吗?等等。


修改

感谢您将表格添加到查询中的字段。如果不了解更多数据,它仍然是非常有限的,但我会尽力帮助你。


1)。 您未在Item_MasterSELECT

中使用GROUP BY

这意味着你要么将它用作过滤器(1:0..1),要么使用乘数(1:1..many),要么两者都用(1:0..many)。

我假设您将其用作过滤器。


2)。 您使用BETWEEN过滤Inv_Date

我假设Inv_Date是DATETIME并且没有时间部分;它总是午夜 - 仅代表日期。在你的情况下给出366个日期(闰年)


这些意味着您有一个表,您希望按两列过滤并按第三列分组。您需要确定这些字段应该按哪个顺序排序,以便尽可能少地给出最终结果。

有6种可能性......

1). Transport_Mode => Item_Name      => Inv_Date  
2). Transport_Mode => Inv_Date       => Item_Name  
3). Item_Name      => Transport_Mode => Inv_Date  
4). Item_Name      => Inv_Date       => Transport_Mode  
5). Inv_Date       => Transport_Mode => Item_Name  
6). Inv_Date       => Item_Name      => Transport_Mode  

如果您先Transport_Mode,则对GROUP BY非常友好。每种可能的模式都将预先组合在一起,准备聚合而无需排序。然后,对于每个组,您只需要过滤记录,使用JOIN过滤Item_NameBETWEEN来过滤Inv_Date

所以,(Transport_Mode, Item_Name, Inv_Date)上的覆盖索引对我来说似乎很好。

但这部分是因为您的查询涵盖了366个Inv_Date值。如果您只对某一天感兴趣,那么最好有(Inv_Date, Transport_Mode, Item_Name)

但是,如果Transport_Mode中的值很少,Item_Name中有很多很多值,那么您的索引中Item_Name之前的Transport_Mode可能会受益吗?< / p>

如果没有关于数据的更多详细信息,我建议创建所有6个索引,填充表格以表示现实生活情况(如果尚未生成),然后运行查询。检查执行计划时,您可以看到优化程序更喜欢的索引。

或者一次创建一个并查询查询,因为它使用不同的索引和执行计划。然后,您可以在所有查询中保留对您最有用的那个,而不仅仅是一个。


但是 ,在所有情况下,请确保您也在itemcode表格上编制Item_Master索引!

答案 1 :(得分:1)

这取决于很多因素。您可以尝试强制使用带有查询提示的索引并比较执行计划(尤其是估计的行数和主键查找的成本)。什么是日期条件的选择性?一般来说,这个查询(实际上它取决于数据结构,但只是作为一个假设)索引(item_name,Transport_Mode)将更好地工作。