我有一个表T,有一个PK Id,两个字段FieldA,FieldB和一个Date字段。
我执行了一个请求(在SQLServer上)。
select top(N) *
from T
where (FieldA=Value1 OR FieldB=Value2) AND Date < GivenDate
ORDER BY Date DESC
如果我在表上有以下两个索引。
(FieldA ASC)
(FieldB ASC)
如果Value1或Value2出现的次数很多,那么这个请求 "执行得不是很好",因为没有Date的信息,引擎必须读取所有匹配的行并进行排序。
我决定将索引改为。
(FieldA ASC, Date DESC)
(FieldB ASC, Date DESC)
但这并没有改变什么:"实际读取的行数 "是匹配值的总行数。
我想象中的引擎应该很聪明,能够从每个Indexes中最多得到N行,然后进行排序(我想)?
它是否能够做到这一点,但是它基于成本的估计足够低,从而决定使用这个执行计划?
对引擎来说肯定不是那么容易猜到的。但有没有其他方法可以改善这种请求呢?
我建议使用SQL管理工作室来检查最佳的索引使用。首先,我会把Date放在第一个位置,因为它是最常用的(即使它在这种情况下没有任何变化)。
其次,如果你能在后面的代码中进行排序,我会推荐它。任何时候,你可以,在代码(Java,C#......)排序的结果。我会快得多,而且你会更好地利用你的索引,因为你不需要Date的索引。
第三,如果你不能在Java或C#代码中进行排序,有时,最好是创建没有排序的select,把结果放到一个有日期索引的临时表中,然后再从这个临时表中进行排序选择。你应该看看执行计划,看看哪种方式最好。
然后,你也可以尝试的是使用包含的索引而不是多列索引。类似于.NET的东西。
CREATE NONCLUSTERED INDEX IX_MYINDEX
ON T(Date)
INCLUDED (FieldA, FieldB)
我希望这能帮助你。如果可能的话,把你的执行计划贴出来,让我们能够看到问题所在。
你确定一个或多个索引被使用了吗?
如果你确认它们没有被使用(我是这么认为的),那么至少可以用以下方法强制使用其中一个索引 用(INDEX (Index_name-here))从T ...如果你想强制使用两个索引,你将不得不对同一个表做一个内联,并在那里设置第二个索引。
总之,解决这个问题的最好方法是在基元类型上建立索引,在你的情况下,这相当于把日期转换为一个整数。
对于这个问题,你有三种选择,在查询中做,在视图中做,或者在结构中添加一些必要的字段,以及必要的代码,在每次插入或更新时自动填写这些数据。
祝贺