索引日期和时间的正确方法时间列

时间:2012-10-13 14:09:45

标签: sql-server

我有一个包含以下结构的表:

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

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

  1. 在这3个日期时间列上设置索引的最佳方法是什么? 2在日期和时间上分开,或者在日期上是1,在复合日期时间上是1,还是其他什么?这个表上发生了很多插入和更新,我想避免过度索引。
  2. 当我写这个问题时,我注意到了长而有点丑陋的计算列定义。我刚才从某个地方捡到它,忘了调查是否有更简单的方法。有没有更简单的方法将日期和时间2组合到datetime2?简单的添加不起作用,我不确定我是否应该避免转换为varchar,组合和回流。

3 个答案:

答案 0 :(得分:4)

很遗憾,您没有提到您正在使用的SQL Server的版本 ....

但如果您使用的是SQL Server 2008或更新,那么您应该转过来:

你的桌子应该有

MyDateTime DATETIME

然后将“only date”列定义为

MyDate AS CAST(MyDateTime AS DATE) PERSISTED

由于您将其设置为持久,因此它会存储在表数据旁边(现在每次查询时都会计算),您现在可以轻松地将其编入索引。

同样适用于MyTime列。

答案 1 :(得分:2)

在两个单独的列中包含日期和时间可能看起来很奇怪,但如果您的查询只使用日期(和/或特别是时间部分),我认为这是一个有效的决定。您可以仅在日期或按时或在(日期,等等)上创建索引等。

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

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

答案 2 :(得分:1)

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

应使用单个DateTime字段,如果提供应用程序所需的日期和时间分辨率,则应使用SmallDateTime

索引该列,然后使用如下查询:

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

通过在结束过滤器上使用<,它仅包含该日期午夜之前的某个时间的结果,该日期是用户选择的结束日期&#34;之后的第二天。这比添加23:59:59更简单,更准确,特别是因为存储的时间可以包括23:59:59到00:00:00之间的微秒。

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