我有关于我在简单的一对表中存储的许多项目的时间序列数据(在此玩具示例中)。现在,这是在MySQL中完成的,但是如果有足够充分的理由尝试在不同的DBMS中解决我的问题,我会不知所措!
ITEM
表具有一个主键和一个可以视为描述的类似文本的列,我们将其称为descr
。 DATAPOINT
表具有一个主键和其他3列:ITEM
表中的外键(称为fk_item
),日期时间我将调用timestamp
并进行浮动我们称为value
的值。此外,在(fk_item, timestamp)
列对上存在联合唯一性约束(我们只希望在给定时间给定项目中DB中有一个值)。
要在其上加上实数,DATAPOINT
表大约有10亿行,这是由于每10k个不同项大约有10万行。
我的问题是关于在这种情况下优化读写性能的能力,以及实施该唯一性约束的最佳方法。
从此数据库中进行的典型读取将涉及少量项目(半打?),我们希望针对这些项目获得给定日期时间范围内的所有值(每个项目包含大约1k点)。为此,拥有一个(fk_item, timestamp)
的索引并对该索引执行联合唯一性标准将非常方便。这种读物背后的动机是:“我想为这3年范围制作2或3个项目的折线图”。
但是,该数据库的典型写入看起来非常不同。这将是为数千个项目中的每一个插入单个数据点,所有项目都具有相同(或少量)时间戳。这种写法的动机可以直观地认为是:“我想为每一项添加昨天的数据点”。因此,对于这种类型的写入,拥有一个(timestamp, fk_item)
的索引并对该索引执行唯一性限制会更实际。
重要的是,对于我的数据和硬件规模而言,这些索引都无法完全放入RAM。
通常,绝大多数写操作每天都在短时间内发生:即,在每天结束时,当天的所有数据都会在15分钟内写入,然后全天进行读操作(但通常不在那15分钟之内。
因此,据我了解,如果我使用经过读取优化的(fk_item, timestamp)
索引构建表(并在其中放置唯一性约束),那么我的典型读取将非常方便。但是我担心我的写入会很慢,因为我们将需要以非连续的方式更新索引。但是,如果我用写优化的(timestamp, fk_item)
索引构建表(并在其中放置唯一性约束),那么我的典型写入将很快,但是典型的读取会受到影响。
有什么办法可以做到两全其美吗?例如,如果我建立两个索引:(fk_item, timestamp)
和 (timestamp, fk_item)
并将唯一性 only 放在两个索引中的最后一个,那会很好?否则,写操作仍将以“慢”的速度进行,因为即使存在写优化索引(例如,检查唯一性约束),读优化索引也需要在任何插入上进行更新,并且该更新将是不连续的?
谢谢!
答案 0 :(得分:0)
简短答案:仅server.use(
session({
secret: "secretsssss",
rolling: false,
resave: false,
saveUninitialized: false,
cookie: {
sameSite: false, // i think this is default to false
maxAge: 60 * 60 * 1000
}
})
);
。
长答案:
就唯一性而言,(fk_item, timestamp)
和(fk_item, timestamp)
是相同的。尽管它们都同样出色地声明了唯一性,但是它们都对 being 唯一性很着迷。有一天,某个特定的物品会在同一秒内显示两次。
您确实提到了“昨天”。因此,如果该条目确实是 day 的小计,则(timestamp, fk_item)
是合理的。
建立索引时,最好将日期/时间项设为 last 。这样(fk_item, date)
可以使用该索引。写作并不在乎(什么)事物的顺序。
WHERE fk_item = 123 AND date BETWEEN ... AND ...
呢?它是,但MySQL的定义为PRIMARY KEY
和一个UNIQUE
。因此,如果INDEX
是合理的,则将其设为PK。这将使需要查看特定项目几行的查询更加高效。
“我想为此3年范围制作2或3个项目的折线图”。 -如果涉及数百万行,则说明您对架构的设计效率低下。您需要建立并维护一个汇总表,其中包含每个项目的每日值。那么它将是数百行,而不是数百万行–更加可行。
返回(fk_item, date)
。如果有1万个不同的项目和INSERTs
,则表中将出现1万个插入位置。这实际上是可以的,并且将与其他订购大致相同的速度。
最好PRIMARY KEY(fk_item, date)
或多行INSERTs
来完成每日LOAD DATA INFILE
。
我从MySQL的角度讲。我说的一些(也许不是全部)适用于其他产品。
除非您打算清除“旧”数据,否则 INSERTs
对于MySQL是一个无用的主意。 (我不能代表Posgres。)
如果随机插入行,则可能会遇到不切实际的性能问题。这是因为您的实际情况将减少“随机性”。您今天PARTITIONing
的工作地点只有1万个,而不是10亿个。明天,它将是“相同”的10K点。
“应该如何构建这样的表”-最小化数据类型(例如,不要将8字节的INSERTs
用于yes / no标志);提供最佳PK(我建议使用BIGINT
)。但是您必须具有暂定(item, day)
才能确定二级索引。在适当的地方进行归一化(SELECTs
),但不要过度归一化(日期)。