4

我有一个具有以下结构的表:

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 通常用于过滤,而 full date-time 用于排序。现在提问:

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

3 回答 3

4

不幸的是,您没有提及您使用的是什么版本的 SQL Server ....

但是,如果您使用的是 SQL Server 2008 或更新版本,您应该扭转这种局面:

你的桌子应该有

MyDateTime DATETIME

然后将“唯一日期”列定义为

MyDate AS CAST(MyDateTime AS DATE) PERSISTED

由于您将其设置为持久化,因此它与表数据一起存储(现在每次查询时都会计算),您现在可以轻松地对其进行索引。

同样适用于MyTime列。

于 2012-10-13T14:39:47.633 回答
2

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

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

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

于 2012-10-13T14:48:41.720 回答
1

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

DateTime应该使用单个字段,或者即使SmallDateTime它提供了您的应用程序所需的日期范围和时间分辨率。

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

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

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

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

于 2012-10-13T14:48:53.383 回答