1

我有一个特定的设计问题一直困扰着我很长一段时间。我有一个大型实时 GPS 位置日志表,其中包含数千个资产的点条目。每项资产每天有数百个积分进入数据库。我有一个索引 IX(asset asc,EventTime asc) 来加快目标资产的点查询。我有一个 LastKnownLocation 表,用于将每个资产与其最近的点相关联。这只为我提供了当前最后一次已知的查找。我的问题是,在给定多个资产的特定查找日期的情况下,有没有人知道一种有效的方法可以查询位置日志表中的最后一个已知位置?“问:2012 年 7 月 1 日结束时我的所有资产都在哪里”

顺便说一句,由于每个资产都使用自己的内部单调事件时间戳报告其点,因此与每个资产相关的表的 LocationLog.LocationLogID auto inc 主键存在隐含的单调关系。这就是我可以使用 MAX Aggregate 的原因。

SELECT MAX(LocationLog.LocationLogID) FROM LocationLog 
WHERE LocationLog.fk_AssetID IN 
(
    //LIST OF required assets for report
) 
AND LocationLog.EventTime <= '2012/07/01 23:59:59'
GROUP BY LocationLog.fk_AssetID

问题是数据库索引 IX 可以快速访问单个资产的所有点。然后这些点按索引中的事件时间排序,因此 dbengine 可能会在索引中的事件时间内进行数据扫描,以查找日期为 <= 查找日期的最大 LocationLogID。自资产在查找日期之前报告以来的时间越长,查找匹配项的扫描时间就越长。

由于我的位置日志有 90+ 百万行,并且像这样增长 1000 个资产查询需要 50 秒。

查找给定查找日期的最后一个已知事件必须是一个众所周知的设计模式,但是它避开了我的搜索。

PS:运行 MSSQL2000,但迁移到 Postgres

4

2 回答 2

1

它可能有助于消除IN(...)

尝试类似的东西

--
--  index on AssetID, EventTime desc
--
select
      AssetID
    , LocationID
    , EventTime
from LocationLog as a
join (
        select AssetID_1
        union
        select AssetID_2
        union
        select AssetID_3
        -- etc, list of assets needed in report
      ) as b on b.AssetID = a.AssetID
where a.EventTime = (select max(xx.EventTime) 
                       from LocationLog as xx 
                      where xx.AssetID = a.AssetID
                        and xx.EventTime <= '2012-08-28 12:05:00')
;
于 2012-08-28T17:06:41.600 回答
0

Two things come to mind:

  • Maintain a materialized view on your locations, storing the end-of-day location for each asset for each day; or
  • Partition, partition, partition! If you only have, say, a week's data in each partition such searches will be much cheaper.

I'd probably create a end_of_day_location table and instead of just clearing my last_known_location table at the end of each day I'd INSERT its contents into end_of_day_location first.

于 2012-08-28T13:50:10.450 回答