Postgres 大文本搜索建议
Postgres Large Text Search Advice
我对数据库很陌生,正在寻找一些高级建议。
情况
我正在使用 Postgres 9.3 构建数据库,数据库中有一个 table 我在其中存储日志文件。
CREATE TABLE errorlogs (
id SERIAL PRIMARY KEY,
archive_id INTEGER NOT NULL REFERENCES archives,
filename VARCHAR(256) NOT NULL,
content TEXT);
内容中的文本长度可以从 1k 到 50MB 不等。
问题
我希望能够对 "content" 列中的数据执行相当快的文本搜索(例如,WHERE CONTENT LIKE '%some_error%')。现在搜索速度非常慢(>10 分钟搜索 8206 行)。
我知道索引旨在解决我的问题,但我似乎无法创建索引——每当我尝试时,我都会收到错误消息,提示索引太大。
=# CREATE INDEX error_logs_content_idx ON errorlogs (content text_pattern_ops);
ERROR: index row requires 1796232 bytes,
maximum size is 8191
我希望得到一些关于如何解决这个问题的建议。我可以更改最大索引大小吗?还是我不应该尝试使用 Postgres 对这么大的文本字段进行全文搜索?
非常感谢任何建议!
文本搜索向量无法处理这么大的数据 --- 请参阅 documented limits。他们的优势是模糊搜索,因此您可以在同一个调用中搜索 'swim' 并找到 'swim,' 'swimming,' 'swam,' 和 'swum'。它们无意取代 grep
.
限制的原因在 source code 作为 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 );
在这里,您将每个日志 行 视为一个 "document." 要搜索,您需要执行类似
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');
我对数据库很陌生,正在寻找一些高级建议。
情况
我正在使用 Postgres 9.3 构建数据库,数据库中有一个 table 我在其中存储日志文件。
CREATE TABLE errorlogs (
id SERIAL PRIMARY KEY,
archive_id INTEGER NOT NULL REFERENCES archives,
filename VARCHAR(256) NOT NULL,
content TEXT);
内容中的文本长度可以从 1k 到 50MB 不等。
问题
我希望能够对 "content" 列中的数据执行相当快的文本搜索(例如,WHERE CONTENT LIKE '%some_error%')。现在搜索速度非常慢(>10 分钟搜索 8206 行)。
我知道索引旨在解决我的问题,但我似乎无法创建索引——每当我尝试时,我都会收到错误消息,提示索引太大。
=# CREATE INDEX error_logs_content_idx ON errorlogs (content text_pattern_ops);
ERROR: index row requires 1796232 bytes, maximum size is 8191
我希望得到一些关于如何解决这个问题的建议。我可以更改最大索引大小吗?还是我不应该尝试使用 Postgres 对这么大的文本字段进行全文搜索?
非常感谢任何建议!
文本搜索向量无法处理这么大的数据 --- 请参阅 documented limits。他们的优势是模糊搜索,因此您可以在同一个调用中搜索 'swim' 并找到 'swim,' 'swimming,' 'swam,' 和 'swum'。它们无意取代 grep
.
限制的原因在 source code 作为 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 );
在这里,您将每个日志 行 视为一个 "document." 要搜索,您需要执行类似
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');