我对数据库很陌生,我正在寻找一些高级别的建议。
情况
我正在使用Postgres 9.3构建一个数据库,在数据库中是一个用于存储日志文件的表。
CREATE TABLE errorlogs (
id SERIAL PRIMARY KEY,
archive_id INTEGER NOT NULL REFERENCES archives,
filename VARCHAR(256) NOT NULL,
content TEXT);
内容中的文字长度可以从1k到50MB不等。
问题
我希望能够对“内容”列中的数据执行相当快速的文本搜索(例如,WHERE CONTENT LIKE'%some_error%')。现在搜索速度非常慢(> 10分钟搜索8206行)。
我知道索引是我的问题的解决方案,但我似乎无法创建索引 - 每当我尝试时我会得到索引太大的错误。
=#CREATE INDEX error_logs_content_idx ON错误日志(内容text_pattern_ops);
错误:索引行需要1796232个字节, 最大尺寸为8191
我希望就如何解决这个问题提出一些建议。我可以更改最大索引大小吗?或者我不应该尝试使用Postgres对文本字段进行全文搜索吗?
非常感谢任何建议!
答案 0 :(得分:3)
文本搜索向量无法处理这么大的数据---请参阅documented limits。他们的力量是模糊的搜索,所以你可以在同一个电话中搜索“游泳”并找到“游泳”,“游泳”,“游泳”和“游泳”。它们并不意味着取代grep
。
限制的原因在source code为MAXSTRLEN(和MAXSTRPOS)。文本搜索向量存储在一个长度为1 MiB的长连续数组中(所有唯一词汇的所有字符总数)。为了访问它们,ts_vector索引结构允许11位用于字长,20位用于其在阵列中的位置。这些限制允许索引结构适合32位无符号整数。
如果文件中有太多独特的单词,或者文字经常重复,则可能会遇到这些限制中的一个或两个 - 如果你有50MB的日志文件和准随机数据,这很可能。< / p>
您确定需要将日志文件存储在数据库中吗?您基本上是在复制文件系统,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 );
在此,您将每个日志行视为“文档”。要搜索,您需要执行类似
的操作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');