如何在Postgres SQL中高效地存储包含字符串的大量数据?

如何在Postgres SQL中高效地存储包含字符串的大量数据?,sql,postgresql,database-design,memory-efficient,Sql,Postgresql,Database Design,Memory Efficient,我有两张桌子: Table 1: Date (String: 'YYYYMMDD'), Path (String: '/user/tom/', a directory path), Size (Bigint: 1293232943, size of directory) Table 2: Date (String: 'YYYYMMDD'), Path (String: '/user/tom/logs/file.txt', a file

我有两张桌子:

Table 1: Date (String: 'YYYYMMDD'), 
         Path (String: '/user/tom/', a directory path), 
         Size (Bigint: 1293232943, size of directory)

Table 2: Date (String: 'YYYYMMDD'), 
         Path (String: '/user/tom/logs/file.txt', a file path), 
         Count (Bigint: 282, number of times file has been opened)
我需要进行几个不同的查询,以收集目录下的总访问计数,该目录可以通过查询表2并查找所有类似于
concat(t1.Path,“%”)
的路径找到。有没有更好的方法来构造这个表,以便像这样的查询是高效的,而且最重要的是,数据库不会占用太多空间

因此,我尝试创建第三个表来存储每个路径的id,虽然查询更复杂,但它存储的数据较少,但由于id没有结构,所以它的意义仍然较小。它为每个路径分配一个数字,只要它不在其中

我正在努力找到最有效的方法,以节省存储这些数据的空间。任何帮助都将不胜感激

我正在努力找到最有效的方法,以节省存储这些数据的空间

将代理PK添加到
表1
中,并参考
表2中的代理PK,以最小化存储。(不管怎样,您通常需要
表1
的主键。)路径往往会变长,因此这应该是值得的

如果可以假定噪声始终存在,则不要存储诸如前导和尾随“/”之类的噪声。您可以将其添加到廉价的显示中

使用适当的日期类型(4字节)

假设
count\u opened
未超出
int
范围(?)。否则请使用
bigint

什么可以或需要不为NULL取决于用例的未知细节

为了方便查看,您可以添加一个视图:

CREATE VIEW table2_full AS
SELECT table1_id
     , '\' || t1.path || '\' || t2.sub_path AS total_path
     , t2.some_date, t2.sub_path, t2.count_opened
FROM   table1 t1
JOIN   table2 t2 USING (table1_id)
。。。收集目录下的总访问计数…
有没有更好的方法来构造这个表,以便像这样的查询是高效的,而且最重要的是,数据库不会占用太多空间

这是非常快的,由PK的索引支持。远远快于为此目的匹配前导字符串(即使支持最佳索引)

为了从仅索引扫描中获得最佳读取性能,您可以在
表2(表1\u id,count\u opened)
上添加另一个多列索引

如果只有查询的路径,请使用子查询查找ID:

SELECT sum(count_opened) AS total_access_count)
FROM   table2
WHERE  table1_id = (SELECT table1_id FROM table1 WHERE path = 'user/tom');

同样,为了获得最佳的读取性能,请在
table1(path,table_id)
上添加一个多列索引。您是否有两个表,或者希望在设计好后有两个表?我想你是在设计桌子

看着

您的日期可以存储为文本(9字节)、日期(8字节)或smallint(2字节)

您的路径可能应该存储为文本(内容+1字节)。如果您可以更具体地说明您的最大大小要求,那么varchar(n)将改进数据库设计的“自我文档”(并占用与文本相同的空间)

您的大小和计数可以存储为smallint(2字节)、int(4字节)或bigint(8字节),具体取决于该列中的最大值。根据您提供的值,size将是int,count将是smallint

根据我的经验,数据库处理整数的速度非常快,尽管索引也会影响这一点。如果yyyymmdd是存储日期值所需的格式,我会将其存储为smallint,而不是字符类型

所以如果你和

date     smallint
path     text
sub-path text
size     int
count    smallint
…给定您提供的值,表1中的每行将为15字节,表2中的每行将为32字节

至于使查询快速,这取决于如何编写查询以及其他因素,如可用的服务器资源和索引

您可以在表中添加代理键,并根据需要设置主键。我将使用int作为代理键,但这取决于表中的最大值(行数)。在索引字段(如主键)上进行连接很快。请记住,另一列表示需要更多的存储空间。但存储成本很低。除非你有特别的空间限制,否则我会选择这个选项


如果不使用代理键,请使用连接(而不是
table2.sub_路径,如concat(table1.path,“%”)
)测试查询性能。喜欢慢。您可以尝试类似于
table1.path=substring(table2.sub\u path from 1表示字符长度(table1.path))
,但在联接表达式中抛出多个计算可能会使情况更糟。

不要将日期值存储为字符串。将它们存储为
date
您希望在表2中存储多少行?
SELECT sum(count_opened) AS total_access_count)
FROM   table2
WHERE  table1_id = (SELECT table1_id FROM table1 WHERE path = 'user/tom');
date     smallint
path     text
sub-path text
size     int
count    smallint