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
上有非聚集索引。
当我运行上面的查询时,它使用表扫描显示它。谁能告诉我如何使用索引扫描进行查询?
答案 0 :(得分:2)
您的查询有三个部分需要排序表
1. JOIN
2. WHERE
条款
3. GROUP BY
您的查询未使用索引,因为其他人被认为更重要。将索引放在其他字段上,并在适当的位置合并索引。
我会提供更多详细信息,但不幸的是,您的查询并未说明哪个字段属于哪个表。有关详细信息,请提供每个表的架构和索引的 完整 详细信息。
另外,了解更多的数据行为会很好:通过Transport_Mode进行挖掘可以给出几个大组还是许多小组? item_name / itemcode是一个表中的唯一键吗?等等。
修改强>
感谢您将表格添加到查询中的字段。如果不了解更多数据,它仍然是非常有限的,但我会尽力帮助你。
1)。 您未在Item_Master
或SELECT
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_Name
和BETWEEN
来过滤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)将更好地工作。