数据库重复值问题(基于先前值的过滤)

时间:2008-09-25 15:35:46

标签: sql performance triggers filtering duplicate-data

本周早些时候,我提出了一个关于在运行时按顺序过滤掉重复值的问题。有一些好的答案,但我过去的数据量是缓慢的,不可行。

目前在我们的数据库中,不会过滤事件值。导致重复的数据值(具有不同的时间戳)。我们需要在运行时和数据库级处理这些数据,这需要花费很多时间(并且不能将其拉入代码,因为它在存储过程中使用了很多)导致高查询时间。我们需要一个可以查询的数据结构,该数据结构已经过滤掉了这个数据存储,因此在运行时不需要额外的过滤。

目前在我们的数据库中

  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','1','2008-05-08 04:03:47.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','0','2008-05-08 10:02:08.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','0','2008-05-09 10:03:24.000'(需要删除此内容)**
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','1','2008-05-10 04:05:05.000'

我们需要什么

  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','1','2008-05-08 04:03:47.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','0','2008-05-08 10:02:08.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337','1','2008-05-10 04:51:05.000'

这似乎微不足道,但我们的问题是我们从无线设备获取此数据,导致无序数据包,我们的网关是多线程的,因此我们无法保证我们得到的值是有序的。有些东西可能会像4秒前的'1'和2秒前的'0'那样进入,但我们已经处理了'1',因为它是第一次进入。我们一直在努力实现这一点。我们无法将数据与数据库中的最新值进行比较,因为最新的数据实际上还没有进入,所以要将数据丢弃,我们就会被搞砸,我们的序列可能完全关闭。因此,目前我们存储每个进入的值,数据库根据时间自动调整...但单位可以发送1,1,1,0并且其有效,因为事件仍处于活动状态,但我们只想存储打开和关闭状态(第一次出现打开状态1,0,1,0,1,0)..我们考虑了触发器,但是每次有新值进入时我们都必须对数据进行洗牌,因为它可能早于最后一条消息,它可以改变整个序列(插入会很慢)。

任何想法?

询问您是否需要任何进一步的信息。

[编辑] PK不工作 - 问题是我们的单位实际上发送了不同的时间戳。所以PK不会起作用,因为1,1,1是相同的......但是有不同的时间戳。它的事件在时间1继续,事件仍然在时间2,它发送给我们两个相同的值不同的时间。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你想要做的只是防止欺骗甚至进入数据库。如果是这种情况,为什么不在前两列上定义PK(或唯一索引)并让数据库为您做繁重的工作。根据您定义的PK或AK,Dupe插入会失败。你的代码(或存储过程)只需要优雅地处理该异常。

答案 1 :(得分:0)

这是一个更新解决方案。性能因索引而异。

DECLARE @MyTable TABLE
(
  DeviceName varchar(100),
  EventTime DateTime,
  OnOff int,
  GoodForRead int
)

INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 1, '2008-05-08 04:03:47.000' 
INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 0, '2008-05-08 10:02:08.000' 
INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 0, '2008-05-09 10:03:24.000'
INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 1, '2008-05-10 04:05:05.000' 

UPDATE mt
SET GoodForRead = 
CASE
  (SELECT top 1 OnOff
   FROM @MyTable mt2
   WHERE mt2.DeviceName = mt.DeviceName
     and mt2.EventTime < mt.EventTime
   ORDER BY mt2.EventTime desc
  )
  WHEN null THEN 1
  WHEN mt.OnOff THEN 0
  ELSE 1
END
FROM @MyTable mt
    -- Limit the update to recent data
--WHERE EventTime >= DateAdd(dd, -1, GetDate())

SELECT *
FROM @MyTable

不难想象基于此的过滤解决方案。它只取决于您想要查找每条记录的先前记录的频率(每次查询或偶尔查看一次)。