我们有一个表记录数据。它以每秒15K行的速度记录。
问题:我们如何将表格大小限制在10亿个最新行?
即。一旦达到1bn行,它就变成一个环形缓冲区,在添加最新的行时删除最旧的行。
触发器可能会加载系统太多。 Here's SO上的触发示例。 我们已经在使用一堆调整来保持加速(例如存储过程,表参数等)。
答案 0 :(得分:2)
除非有大约10亿的魔法,否则我认为你应该考虑其他方法。
首先想到的是对数据进行分区。比如说,将一小时的数据放入每个分区。这将导致分区中大约15,000 * 60 * 60 = 5400万条记录。大约每20个小时,您可以删除一个分区。
分区的一大优势是插入性能应该很好,并且您不必删除单个记录。根据查询负载,索引和其他因素,可能会有额外的开销。但是,由于没有额外的索引和主要是插入的查询负载,它应该比尝试每秒删除15,000条记录以及插入更好地解决您的问题。
答案 1 :(得分:0)
这是我的建议:
insert
新的行,并根据行号update
相应的行。这实际上是你在其他环境中使用环形缓冲区的方法。你不会继续分配内存和删除;你只是一遍又一遍地覆盖同一个数组。
更新:更新doesn't actually change the data in place,正如我所想的那样。所以这可能效率不高。
答案 2 :(得分:0)
我没有完整的答案,但希望有一些想法可以帮助你开始。
我会在表格中添加某种数字列。此值将增加1,直到达到要保留的行数。此时,该过程将切换到update
语句,覆盖前一行而不是插入新行。您显然无法使用此列来确定行的顺序,因此如果您还没有,我还会添加一个时间戳列,以便您可以按时间顺序对它们进行排序。
为了协调跨事务的计数器值,您可以使用序列,然后执行模除法以获得计数器值。
为了处理表中的任何空白(例如有人删除了某些行),您可能需要使用merge
语句。如果行丢失则应执行插入,如果存在则执行更新。
希望这有帮助。
答案 3 :(得分:0)
只是想在评论中写一个复杂的想法。
创建一些日志表,例如3,Log1,Log2,Log3
CREATE TABLE Log1 (
Id int NOT NULL
CHECK (Id BETWEEN 0 AND 9)
,Message varchar(10) NOT NULL
,CONSTRAINT [PK_Log1] PRIMARY KEY CLUSTERED ([Id] ASC) ON [PRIMARY]
)
CREATE TABLE Log2 (
Id int NOT NULL
CHECK (Id BETWEEN 10 AND 19)
,Message varchar(10) NOT NULL
,CONSTRAINT [PK_Log2] PRIMARY KEY CLUSTERED ([Id] ASC) ON [PRIMARY]
)
CREATE TABLE Log3 (
Id int NOT NULL
CHECK (Id BETWEEN 20 AND 29)
,Message varchar(10) NOT NULL
,CONSTRAINT [PK_Log3] PRIMARY KEY CLUSTERED ([Id] ASC) ON [PRIMARY]
)
然后创建分区视图
CREATE VIEW LogView AS (
SELECT * FROM Log1
UNION ALL
SELECT * FROM Log2
UNION ALL
SELECT * FROM Log3
)
如果您使用的是SQL2012,则可以使用序列
CREATE SEQUENCE LogSequence AS int
START WITH 0
INCREMENT BY 1
MINVALUE 0
MAXVALUE 29
CYCLE
;
然后开始插入值
INSERT INTO LogView (Id, Message)
SELECT NEXT VALUE FOR LogSequence
,'SomeMessage'
现在你只需要在某种时间表上截断日志表
如果您没有sql2012,则需要以其他方式创建序列
答案 4 :(得分:0)
我自己正在寻找类似的东西(使用表作为循环缓冲区)但似乎更简单的方法(对我来说)只是定期删除旧条目(例如最低的 ID 或最低的创建/上次修改日期时间或超过一定年龄的条目)。它不是一个循环缓冲区,但对于某些人来说,它可能是一个足够接近的近似值。 ;)