如何在此日志记录表上优化此查询?

Hug*_*une 2 performance database-design sql-server sql-server-2012 denormalization

我正在尝试为记录事件的表格优化表格布局。

日志表包含三个相关的列:Timestamp, ItemId, LocationId
每行表示在给定的timeitem已经在某个 看到了某个location

2017-01-01 10:00    Item A has been seen at location 1
2017-01-01 10:01    Item A has been seen at location 1
2017-01-01 11:00    Item B has been seen at location 1
2017-01-01 11:01    Item B has been seen at location 2
2017-01-01 11:02    Item A has been seen at location 2
2017-01-01 11:03    Item B has been seen at location 1
Run Code Online (Sandbox Code Playgroud)

大约有 100 个不同的位置、每天 20.000 个新项目、每天一百万个事件和 14 天的日志。

现在我需要对这些数据运行查询,例如:

  • 哪些项目在时间 '2017-01-01 11:00' 位于位置 '1'
    (= 哪些项目在时间 '2017-01-01 11:00' 之前在位置 1 上看到,并且在其他地方没有看到在 1 但在 '2017-01-01 11:00' 之前看到

为了获得这些数据,我可以执行

SELECT DISTINCT  ItemId     
FROM events e1 
WHERE LocationId = 1
  AND e1.TimeStamp < '2017-01-01 11:00'
  AND NOT EXISTS (SELECT 1 FROM events e2
                  WHERE e2.LocationId <> e1.LocationId
                    AND e2.ItemId = e1.ItemId
                    AND e2.TimeStamp >= e1.TimeStamp
                    AND e2.TimeStamp <'2017-01-01 11:00')
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

目前,当数据库负载为零时,此查询大约需要 15 秒。目标是在低于 100 毫秒的时间内执行此查询,并且负载很重。我认为目前的设计不可能做到这一点。

我有一个关于项目和位置的索引,以及一个关于时间戳的聚集索引

是否有表格布局可以让我更有效地执行此查询?

或者是否有可以与现有表一起使用的查询?

RDF*_*ozz 5

您可以尝试不同的查询:

SELECT ItemID
  FROM (SELECT ItemID
              ,ROW_NUMBER() OVER (PARTITION BY ItemID ORDER BY TimeStamp DESC) rn
              ,LocationId
          FROM events
         WHERE TimeStamp < '2017-01-01 11:00'
       ) e1
  WHERE LocationId = 1
    AND rn = 1
;
Run Code Online (Sandbox Code Playgroud)

没有承诺这会做得更好(实际上可能更糟);这只是一种不同的方法。

另外 - 如果有意义,您可能希望对可能的TimeStamp值设置一个下限;如果您可以在查找时间之前 12 小时以上忽略所有内容,则可以消除大量行。