2015-01-15 2 views
6

저는 데이터베이스가 아주 새로워서 높은 수준의 조언을 구하고 있습니다.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 콘텐츠 LIKE '%의 some_error %'). 현재 검색은 매우 느립니다 (8206 행까지 검색하려면 10 분 초과).

나는 색인 생성이 내 문제의 해결책으로 의도되었지만 색인을 만들 수있는 것처럼 보이지 않는다. 색인을 너무 많이 만들면 오류가 발생한다.

=# CREATE INDEX error_logs_content_idx ON errorlogs (content text_pattern_ops);
ERROR: index row requires 1796232 bytes, maximum size is 8191

이 문제를 해결하는 방법에 대한 조언이 필요했습니다. 최대 색인 크기를 변경할 수 있습니까? 아니면 이처럼 큰 텍스트 필드에서 전체 텍스트 검색을 위해 Postgres를 사용하려고하지 않아야합니까?

많은 조언을드립니다.

+2

아마도 전체 텍스트 검색/색인 생성을 원할 것입니다. http://www.postgresql.org/docs/9.1/static/textsearch-intro.html. –

+1

이 답변은 도움이 될 수도 있습니다. http://stackoverflow.com/questions/1566717/postgresql-like-query-performance-variations/13452528#13452528 –

+0

안녕하세요, 조언을 주셔서 감사합니다. 이미 텍스트 검색 문서를 살펴본 결과 색인 제한에 대한 정보를 찾을 수 없었습니다.두 번째 주석은 위에서 언급 한 text_pattern_ops 인덱스를 만드는 것에 대해 설명합니다. 인덱스는 너무 커서 인덱스에 대한 오류를 반환합니다. – JBeFat

답변

2

텍스트 검색 벡터는 큰 데이터를 처리 할 수 ​​없습니다. documented limits을 참조하십시오. 그들의 힘은 모호한 검색이므로 동일한 통화에서 '수영'을 검색하고 '수영', '수영', '수영'및 '수영'을 검색 할 수 있습니다. 그들은 grep을 대체 할 것이 아닙니다.

제한의 이유는 source code의 MAXSTRLEN (및 MAXSTRPOS)입니다. 텍스트 검색 벡터는 길이가 1 MiB까지의 하나의 길고 연속적인 배열로 저장됩니다 (모든 고유 어휘의 모든 문자 합계). 이들에 액세스하기 위해 ts_vector 인덱스 구조는 단어 길이에 대해 11 비트와 배열에서의 위치에 대해 20 비트를 허용합니다. 이러한 제한은 인덱스 구조가 32 비트 부호없는 int에 맞도록합니다.

파일에 고유 단어가 너무 많거나 단어가 매우 자주 반복되는 경우이 제한 중 하나 또는 둘 모두에 해당 될 수 있습니다. 준 임의 데이터가있는 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); 

을 여기에서, 당신은 각각으로 라인 로그 치료 "문서." 검색하려면 다음과 같이하십시오.

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

제안에 감사드립니다. 이후에는 행마다 단일 로그 행을 저장하는 것으로 전환했습니다. 아직 색인 생성을 시도하지는 않았지만 -이 방법을 사용해 보았지만 멋지게 작동합니다. 다시 한 번 감사드립니다! – JBeFat

관련 문제