如何编写查询以更好的方式检索两个日期?

时间:2016-12-31 09:50:53

标签: sql sql-server query-optimization

这是我尝试的SQL查询

SELECT 
    TransactionNumber,Time
FROM 
    [HQMatajer].[dbo].[Transaction]
WHERE 
    Time>='2015-01-01' and Time<='2015-12-31'

总记录返回280万。这需要10秒钟。

我也为TimeTransactionNumber创建了一个索引。

还有什么我需要做的比这更快的行?

由于

2 个答案:

答案 0 :(得分:5)

280万行是很多数据!无论如何,它都需要一个“长”(长期相对 - 对于280万行来说是10秒是合理的)。如果您想改进它,请返回较少的数据。

有两种选择可能会带来微小的改善:

  • CLUSTERED列上创建Time注意一个表只允许1个聚簇索引。因此,当考虑其他因素时,这可能不太好。
  • Time INCLUDE
  • TransactionNumer上创建索引

但无论哪种方式,你的问题都不是查询/索引,而是数据量。

其他信息

  • 使用2个单独的索引不会有任何帮助。您的查询只能使用1个索引(无论哪个最好)。
  • 我假设您的TransactionNumber确实是数字数据类型而不是我经常看到的可疑“字符串数字”之一。如果您使用某种形式的varchar来存储TransactionNumber,那么您最好将其更改为intbigint。这些类型需要较少的字节来存储==&gt;意思是少数据==&gt;意味着更好的表现。
  • 除非您截断Time列的时间部分,否则您的查询目前存在错误。显然,您打算返回当年的所有交易。但目前您将错过12月31日未在00:00发生的所有交易。要修复此时间范围,应按如下方式过滤查询:
    • Time >= StartOfRange and Time < StartOfNextRange
    • E.g。 Time >= '2015-01-01' and Time < '2016-01-01'
    • 注意:在第二个条件中严格注意<。这包括明年年初 之前的所有交易

数学

为什么我说280万行的一些计算是“要返回的大量数据”。

  • 您返回TransactionNumberTime。我将分别假设每行4和8个字节。 (可能会更多,但这是 非常保守的 估算。)
  • 那是12 bytes * 2,800,000 = 33,600,000 bytes(大约32 MB)。
  • 这只是返回的最小数据。请记住,处理的数据要多得多。包括表的其他列和索引树。
  • 要在服务器和客户端之间在10秒内传输33.6 MB的数据,需要:32 MB * 8 / 10 = 25.6 I.e。平均传输速率超过每秒25兆比特。

结论

无论你想要做什么,都需要280万行,可能需要重新考虑你的方法。但是,如果你说的是一年一次的工作 - 那么10秒真的值得担心吗?

答案 1 :(得分:0)

也许如果你将更多的计算预先放在变量中,只有在你获得更好的性能时才会执行它们。可能不会产生太大的影响,甚至可能对性能有害,但尝试很有趣。

DECLARE @midwaySeconds int = DATEDIFF(s, '2015-1-1 00:00:00', '2015-12-31 23:59:59') / 2
DECLARE @midwayDate datetime2 = DATEADD(s, @midwaySeconds, '2015-1-1 00:00:00')
SELECT 
    TransactionNumber,Time
FROM 
    [HQMatajer].[dbo].[Transaction]
WHERE 
    ABS(DATEDIFF(s, Time, @midwayDate)) < @midwaySeconds