存储数据的最佳方法:许多列与每天10,000行新行的箱子



在检查了stackoverflow上的许多类似问题后,似乎上下文可以说出哪种方式是持有数据的最佳方法...

简短的故事,我在一个只包含3列的非常简单的表中添加了10,000多行新的数据。我永远不会更新行,只能进行选择,分组和平均值。我正在寻找存储这些数据以使平均计算尽可能快的方式的最佳方法。

要使您在上下文中,我正在使用FFT分析一个录制的音频文件(在声音混音工作室中粉红色的噪音播放(。单个音频文件的结果始终以相同的格式:频率箱的ID(整数(及其在分贝中的值(浮点值(。我想将这些值存储在postgresql db中。

频率(宽度= 8Hz(的每个bin(频段(在分贝中获得振幅。第一个垃圾箱被忽略,所以它像这样(不是实际的DB值(:

  • bin 1:8Hz -16Hz,-85.0db
  • bin 2:16Hz -32Hz,-73.0db
  • bin 3:32Hz -40Hz,-65.0dB
  • ...
  • bin 2499:20,000Hz -20,008Hz,-49.0db

目标是存储从8Hz到20,008Hz的每个垃圾箱的振幅(1箱覆盖8Hz(。

许多行方法

对于每个分析的音频文件,将有3列的2,499行:"分析UID"," BIN ID"one_answers" DB"。

对于每个工作室(4(,每天都有一个记录,该记录将在数据库中附加(每天是4倍2,499 = 9,996个新行(。

在一个工作室中的录制后,使用新的2,499行来显示频率响应的图。

我担心的是,我们还需要制作单个工作室中每个垃圾箱的平均DB值的图5-30天,以查看频率响应是否会随着时间的推移显着变化(因此告诉我们一个工作室需要校准(。

我想出了许多行方法的以下数据结构:

"分析"表:

  • 分析uid(序列(
  • studiouid(外键(
  • AnalySistimestamp

"分析_Results"表:

  • Analysissuid(外键(
  • freq_bin_id(integer(
  • amplitude_db(float(

这是存储数据的最佳方式吗?一张单表每天保持近10,000行,并进行5个或更多分析的平均值,通过分析和freq_bin_ids进行分组?那会给我2,499行(每行都对应于垃圾箱,并给我平均的数据库值(。

许多列方法:

我以为我可以相反地做到这一点,将频率箱打破4桌子(低,低,高,高,高(。由于Postgres文档表示列的限制为" 250-1600",这取决于列类型" " ,因此将4个包含在625列(2,499/4(约为垃圾箱的表(2,499/4(的表是现实的,每个表都代表垃圾箱并包含一个垃圾箱"。db"值,就像这样:

"低"表:

  • Analysissuid(外键(
  • freq_bin_id_1_amplitution_db(float(
  • FREQ_BIN_ID_2_AMPLETITE_DB(float(
  • ...
  • FREQ_BIN_ID_625_AMPLETITE_DB(float(

" med_low"表:

  • Analysissuid(外键(
  • FREQ_BIN_ID_626_AMPLETITE_DB(float(
  • FREQ_BIN_ID_627_AMPLETITE_DB(float(
  • ...
  • FREQ_BIN_ID_1250_AMPLETITE_DB(float(

等...

如果服务器只需要通过分析uid进行分组并进行平均值,则平均值会更快地计算?

行不是一个问题,但是,您插入所述行的方式。如果插入时间是主要问题之一,请确保您可以插入它们或使用较少行的格式。

您可以以JSONB格式存储所有数据,尤其是因为您不会对数据进行任何更新 - 一次将其全部存储在一个表中可能很方便,但是性能可能会更少。

无论如何,由于您没有更新数据,因此(通常默认(填充器为100。

我不会使用"多列"方法作为您所谈论的数据数量确实不是那么多。使用您的第一个示例2表和几列的示例很可能是完成结果的最佳方法。

索引以下列可能很有用:Analysis_results.freq_bin_id分析。

将数据分解为不同的部分,这将取决于您正在运行的查询类型。如果您要查看所有Freq垃圾箱,那么使用多个桌子就会很麻烦,什么也没收。

如果一次仅在某个freq_bin上查询,则理论上可能会有所帮助,但是,您基本上是在做表分区,一旦进入该土地,您也可以为每个频带进行分区。<<<<<<<<<<<<<<<<<</p>

如果我是您,我会创建您的第一个表结构,并填充价值30天的数据并查询。您可能(就像我们经常一样(过度分析了这种情况。Postgres可以非常非常快。

请记住,您要分析的原始数据是按照绝对最大值的每天(5(MEG的顺序。分析150 MB的数据对于用现代硬件运行的DB索引并正确存储的数据不会出汗。

优化器将在"较小"表中找到正确的行真的非常快,可能会缓存所有这些,然后去寻找子行,它将确切知道ID和范围搜索的内容。如果您的数据全部按时间顺序插入,那么很有可能在很少的读物中读取所有内容。

我主要关心的是插入速度,因为如果您不做散装插件,则进行10,000个插入物可能需要一段时间。

测量结果表现良好,您可以使用数组,使用FREQ_BIN作为索引(注意:索引在SQL中是基于1的(这具有将Aray存储在烤储存中的附加优势,使fysical桌子保持较小。


CREATE TABLE herrie
    ( analysisUID serial NOT NULL PRIMARY KEY
    , studioUID INTEGER NOT NULL REFERENCES  studio(studioUID)
    , analysisTimestamp TIMESTAMP NOT NULL
    , decibels float[]      -- array with 625 measurements
    , UNIQUE (studioUID,analysisTimestamp)
    );

最新更新