Postgres大文本搜索建议

时间:2015-01-15 17:48:37

标签: postgresql

我对数据库很陌生,我正在寻找一些高级别的建议。

情况
我正在使用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对文本字段进行全文搜索吗?

非常感谢任何建议!

1 个答案:

答案 0 :(得分:3)

文本搜索向量无法处理这么大的数据---请参阅documented limits。他们的力量是模糊的搜索,所以你可以在同一个电话中搜索“游泳”并找到“游泳”,“游泳”,“游泳”和“游泳”。它们并不意味着取代grep

限制的原因在source code为MAXSTRLEN(和MAXSTRPOS)。文本搜索向量存储在一个长度为1 MiB的长连续数组中(所有唯一词汇的所有字符总数)。为了访问它们,ts_vector索引结构允许11位用于字长,20位用于其在阵列中的位置。这些限制允许索引结构适合32位无符号整数。

如果文件中有太多独特的单词,或者文字经常重复,则可能会遇到这些限制中的一个或两个 - 如果你有50MB的日志文件和准随机数据,这很可能。< / p>

您确定需要将日志文件存储在数据库中吗?您基本上是在复制文件系统,greppython可以很好地进行搜索。但是,如果你真的需要,你可以考虑这个:

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');