我对数据库很新,我正在寻找一些高级别的建议.
我正在使用Postgres 9.3构建数据库的情况在数据库中是一个表,我在其中存储日志文件.
CREATE TABLE errorlogs (
id SERIAL PRIMARY KEY,
archive_id INTEGER NOT NULL REFERENCES archives,
filename VARCHAR(256) NOT NULL,
content TEXT);
Run Code Online (Sandbox Code Playgroud)
内容中的文本长度可以在1k到50MB之间变化.
问题
我希望能够对"内容"列中的数据执行相当快速的文本搜索(例如,WHERE CONTENT LIKE'%some_error%').现在搜索速度非常慢(> 8分钟搜索8206行).
我知道索引是我的问题的解决方案,但我似乎无法创建索引 - 每当我尝试我得到索引太大的错误.
=#CREATE INDEX error_logs_content_idx ON错误日志(content text_pattern_ops);
错误:索引行需要1796232个字节,最大大小为8191
我希望就如何解决这个问题提出一些建议.我可以更改最大索引大小吗?或者,我是否应该尝试使用Postgres对文本字段进行全文搜索?
任何建议都非常感谢!
小智 4
文本搜索向量无法处理这么大的数据——请参阅记录的限制。它们的优势在于模糊搜索,因此您可以在同一调用中搜索“游泳”并找到“游泳”、“游泳”、“游泳”和“游泳”。它们并不是要取代grep.
限制的原因在源代码中为 MAXSTRLEN(和 MAXSTRPOS)。文本搜索向量存储在一个长的、连续的数组中,长度最多为 1 MiB(所有唯一词位的所有字符的总和)。为了访问这些,ts_vector 索引结构允许 11 位字长和 20 位数组中的位置。这些限制允许索引结构适合 32 位无符号整数。
如果文件中有太多唯一的单词,或者单词重复得非常频繁,那么您可能会遇到其中一个或两个限制——如果您有包含准随机数据的 50MB 日志文件,则很可能会遇到这种情况。
您确定需要将日志文件存储在数据库中吗?您基本上是在复制文件系统,或者grep可以python很好地在那里进行搜索。不过,如果您确实需要,您可以考虑:
CREATE TABLE errorlogs (
id SERIAL PRIMARY KEY
, archive_id INTEGER NOT NULL REFERENCES archives
, filename VARCHAR(256) NOT NULL
);
CREATE TABLE log_lines (
line PRIMARY KEY
, errorlog INTEGER REFERENCES errorlogs(id)
, context TEXT
, tsv TSVECTOR
);
CREATE INDEX log_lines_tsv_idx ON log_lines USING gin( line_tsv );
Run Code Online (Sandbox Code Playgroud)
在这里,您将每个日志行视为一个“文档”。要搜索,你会做类似的事情
SELECT e.id, e.filename, g.line, g.context
FROM errorlogs e JOIN log_lines g ON e.id = g.errorlog
WHERE g.tsv @@ to_tsquery('some & error');
Run Code Online (Sandbox Code Playgroud)