2012-10-13 54 views
3

我有如下结构的表:有道索引日期和时间列

create table MyTable (
    ID int identity, 
    Whatever varchar(100), 
    MyTime time(2) not null, 
    MyDate date not null, 
    MyDateTime AS (DATEADD(DAY, DATEDIFF(DAY, '19000101', [MyDate]), 
          CAST([MyDate] AS DATETIME2(2)))) 
) 

计算列添加日期和时间到单个DATETIME2字段。对阵表大部分查询有以下条款的一种或多种:

... WHERE MyDate < @filter1 and MyDate > @filter2 
... ORDER BY MyDate, MyTime 
... ORDER BY MyDateTime 

简而言之,日期通常用于过滤和完整的日期,时间被用于排序。现在的问题:

  1. 最好的方法来设置这3个日期时间柱的指数? 2日期和时间单独或可能1日期和复合日期时间1,或其他?在这个表上有很多插入和更新,我想避免索引过多。
  2. 正如我写这个问题,我注意到长和有点丑陋的计算列定义。我从前一个地方捡起它,忘记调查是否有更简单的方法。有没有更简单的方法将date和time2合并到datetime2中?简单的添加不起作用,我不知道我是否应该避免投射到varchar,合并和投射回来。
+1

我只需要问清楚:为什么你需要单独的日期和时间列? –

+0

有一种感觉,这个问题会弹出..它可以被修改成一个单一的datetime2列,但往往只有时间部分的变化和大量的查询按日期部分过滤,并剥离时间创建的问题在选择过去在x和y之间不会包含y日期,因为时间默认为00:00:00,需要将其更改为23:59:59以包含整个日期。 – Jeti

回答

1

将日期和时间分成两个单独的列可能看起来很奇特,但如果您只有使用日期(和/或仅使用时间部分)的查询,我认为这是一个有效的决定。你可以创建一个仅在日期或按日期(日期,无论)的指数等。

我不明白的是为什么你也有计算日期时间列。没有理由存储这个值。它可以在需要时轻松计算。

如果您需要按日期时间排序,则可以使用ORDER BY MyDate, MyTime。有一个(MyDate, MyTime)索引这应该没问题。范围日期时间查询也将使用该索引。

+0

为了便于维护查询,我添加了计算列,因为无论何时将日期时间包含在查询的SELECT子句中,日期和时间都将作为单列返回。添加该计算列似乎比向10个以上的查询添加相同的公式更容易,并且它应该执行相同的操作,因为它没有保留,不是吗? – Jeti

+0

这听起来很有道理。但你不需要坚持和索引它。 '(MyDate,MyTime)'索引将用于您提供的查询。 (不应该使用'ORDER BY MyDateTime') –

+0

我想我会坚持这个解决方案,因为它只需要很少的修改,而且我感觉更舒服的是有单独的日期和时间列,因为对新查询的奇怪请求是每天从我的雇主进来。价值分割似乎现在是安全的。谢谢 – Jeti

4

不幸的是,你没有提到版本您正在使用的SQL Server ....

但是,如果你的SQL Server 2008 或更新上,你应该把这个什么各地:

你的表应该有

MyDateTime DATETIME 

,然后定义 “仅日期” 一栏为

MyDate AS CAST(MyDateTime AS DATE) PERSISTED 

既然你把它坚持,它的旁边存储在表数据(现在计算在每次查询它的时候),你可以很容易地现在建立索引。

同样适用于MyTime列。

+0

在这种情况下,您是否建议只索引MyDateTime? 'PERSISTED'甚至需要在计算的MyDate上添加一个额外的索引? – Jeti

+0

@Jeti:如果你选择'MyDate' - 我会在MyDate上创建一个索引,看看它是否有帮助,然后我会创建另一个独立的'MyDateTime'上的索引,看看这对你的查询是否有所帮助,如果是的话 - 离开索引 - 如果不是的话,再折腾一次 –

+0

@Jeti:和是的 - 我总是尝试使用'PERSISTED' - 即使你可以在技术上创建一个索引它。如果该数据每分钟不会更改10次,那么保留计算结果并仅在“基本”列值发生更改时重新计算才有意义。 –

1

答案不在您的索引中,它在您的查询中。

应使用一个DateTime字段,或者甚至使用SmallDateTime(如果该字段提供应用程序所需的日期和时间分辨率范围)。

指数该列,然后使用查询这样的:

SELECT * FROM MyTable WHERE 
    MyDate >= @startfilterdate 
    AND MyDate < DATEADD(d, 1, @endfilterdate); 

通过在端部过滤器使用<,它只包括日期,这是所选择的用户后一天的午夜之前从某个结果“结束日期”。这比添加23:59:59更简单也更准确,尤其是因为存储的时间可能包括23:59:59和00:00:00之间的微秒。

在它们上使用持久列和索引会浪费服务器资源。

+0

正如我的评论@ypercube所发表的那样,我现在坚持使用分隔的列,因为在不久的将来我将不得不按照时间组件进行过滤,上帝知道还有什么如果有任何更改请求来通过。 – Jeti

相关问题