如何在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