在单一表格上进行排序查询

问题描述 投票:0回答:2

我有一个表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 sql-server sql-order-by query-performance
2个回答
0
投票

我建议使用SQL管理工作室来检查最佳的索引使用。首先,我会把Date放在第一个位置,因为它是最常用的(即使它在这种情况下没有任何变化)。

其次,如果你能在后面的代码中进行排序,我会推荐它。任何时候,你可以,在代码(Java,C#......)排序的结果。我会快得多,而且你会更好地利用你的索引,因为你不需要Date的索引。

第三,如果你不能在Java或C#代码中进行排序,有时,最好是创建没有排序的select,把结果放到一个有日期索引的临时表中,然后再从这个临时表中进行排序选择。你应该看看执行计划,看看哪种方式最好。

然后,你也可以尝试的是使用包含的索引而不是多列索引。类似于.NET的东西。

CREATE NONCLUSTERED INDEX IX_MYINDEX
ON T(Date)
INCLUDED (FieldA, FieldB)

我希望这能帮助你。如果可能的话,把你的执行计划贴出来,让我们能够看到问题所在。


0
投票

你确定一个或多个索引被使用了吗?

如果你确认它们没有被使用(我是这么认为的),那么至少可以用以下方法强制使用其中一个索引 用(INDEX (Index_name-here))从T ...如果你想强制使用两个索引,你将不得不对同一个表做一个内联,并在那里设置第二个索引。

总之,解决这个问题的最好方法是在基元类型上建立索引,在你的情况下,这相当于把日期转换为一个整数。

对于这个问题,你有三种选择,在查询中做,在视图中做,或者在结构中添加一些必要的字段,以及必要的代码,在每次插入或更新时自动填写这些数据。

祝贺

© www.soinside.com 2019 - 2024. All rights reserved.