首先,这个数据库问题可能与数据库无关,但我使用的是Sql Server 2008,如果它有针对此问题的专门解决方案,但如果您不是MS Sql Server人员请继续阅读..请:)
好的,我在一个包含游戏数据的日志文件中读到。例如。当一个玩家连接,断开连接,做东西等等。没什么太难的。效果很好。
现在,有两个日志文件条目类型是
我正在努力追踪的是当前连接的玩家,以及游戏。 所以我最初想到的是创建第二个表,其中包含每个玩家最新的连接。当玩家断开/失去连接时,我会从第二个表中删除此条目。
例如
Table 1: LogEntries
LogEntryId INT PK NOT NULL
EntryTypeId TINYINT NOT NULL
PlayerId INT NOT NULL
....
Table 2: ConnectedPlayers
LogEntryId INT FK (back to LogEntries table) NOT NULL
然后,我想我可以使用触发器将此插入缓存数据到ConnectedPlayers表中。不要忘记,如果它是一个触发器,它需要handle multiple records,更新和删除。
但我不确定这是不是最好的方法。就像,我可以拥有索引视图吗?
我很想知道别人对此的看法。
哦,还有一件事:为了简单起见,我们假设当播放器掉线/延迟/调制解调器芯片等时,应用程序足够聪明地知道这一点并且将其记录为LostConnection条目。没有虚假用户被报告为连接,当他们真的意外断开连接等等时
我在想,也许我可以使用view
代替? (我可以索引这个视图,如果我想,也:) :)通过Partitioning
我的结果,我可以得到最新的事件类型,每个玩家..事件是NewConnection
或者LostConnection
。然后只抓住那些最新的NewConnection ..这意味着他们已连接。没有第二个表/触发器/额外插入.NET代码/任何需要的......
例如..
SELECT LogEntryId, EntryTypeId, PlayerId
FROM
(SELECT LogEntryId, EntryTypeId, PlayerId
RANK() OVER (PARTITION BY PlayerId ORDER BY LogEntryId DESC) AS MostRecentRank
FROM LogEntries
WHERE (EntryTypeId = 2 -- NewConnection
OR EntryTypeId = 4 -- LostConnection)
) SubQuery
WHERE MostRecentRank = 1
听起来怎么样?
答案 0 :(得分:1)
您不需要第二个表,但是您需要一个日期列,我假设它是日志数据的一部分。我会规范化数据并避免过早优化的诱惑。确保为关键列编制索引,主要是查询时的LogEntryDate
和PlayerId列。
然后,使用标准聚合查询确定每个用户的最新日志条目,然后筛选出未连接的用户。您可以通过仅选择过去24小时(或上周或对您的应用程序有意义的任何内容)的日志条目来进一步优化此操作。
select l.*
from (
select PlayerId, max(LogEntryDate) as MaxLogEntryDate
from LogEntries
where EntryTypeId in (2,4)
and LogEntryDate > GetDate() - 7 --only look at the last week, as connections older than that have timed out
group by PlayerId
) lm
inner join LogEntries l on lm.PlayerId = l.PlayerId and lm.MaxLogEntryDate = l.LogEntryDate
where l.EntryTypeId = 2 --new connections only
如果您发现自己仍未达到查询速度,则会查看优化策略。您似乎不愿意在应用程序层中缓存,因此您的索引视图提议将起作用。您可以使用上面的查询作为此基础,以创建包含布尔IsConnected
列的播放器视图。
注意:如果您没有收到每个日志条目的日期,但游戏会生成LogEntryId,那么它应该可以替代日期。如果您在插入时生成LogEntryId,我会提醒您不要依赖它,因为只需要一次乱序导入就可以抛弃所有数据。
答案 1 :(得分:0)
根据原始表 LogEntries 的大小,这几乎看起来有点过分。
触发器必须随着对原始表的每次更改而更新,如果使用正确的索引,当您需要数据时,简单查询可以为您提供这些结果。
因此我会反对辅助表的选项。
答案 2 :(得分:0)
我会创建一个is_connected标志,login_time,这就是它。 您可以使用简单的MySQL查询每10/60秒检查一次,并将数据缓存到文件中。
其中is_connected = 1,按login_time限制订购10/20/100 ...
第二张桌子看起来太多而且毫无用处。额外的缓存(如果需要,在一个巨大的数据库中......)可以在文件上完成。
答案 3 :(得分:0)
我个人会使用一个视图来获取每个玩家最新的NewConnection或LostConnection(以较新者为准),这意味着您需要在日志中添加某种日期时间戳或者ID不断增加,以及然后筛选进一步丢弃所有LostConnection条目。这将使所有玩家都拥有NewConnection而没有更新的LostConnection,因此它们已连接。
这种方法可能遇到的问题是日志表可能很大。我可能会尝试使用timestamp列上的索引或您用来确定“最新”条目的列的性能测试。
答案 4 :(得分:0)
据我所知,你真正需要的是
玩家(ID) 游戏(ID) 连接(PlayerID,GameID,LastActivity DateTime) ..
@interestingTime是当前
之前的一段时间select PlayerID, GameID
from Connection
where LastActivity > @interestingTime
为您提供所有当前连接的玩家。
select PlayerID, GameID
from Connection
where LastActivity <= @interestingTime
让你失去联系。