Postgresql 全文搜索比 sqlite fts 搜索慢 8 倍
Postgresql full text search 8 times slower than sqlite fts search
所以我想做一些全文搜索,查看了如何使用 sqlite 进行搜索,实现了它并认为它很慢。所以我选择了 postgresql,因为我在过去几年一直在使用该数据库。
我有一个非常简单的 table + 触发器和一个索引:
CREATE TABLE submission
(
id TEXT NOT NULL,
subreddit_id TEXT NOT NULL,
author TEXT,
created_utc INTEGER,
title TEXT NOT NULL,
selftext TEXT,
permalink TEXT,
num_comments INTEGER,
score FLOAT,
upvote_ratio FLOAT,
fts TSVECTOR,
UNIQUE (id, subreddit_id)
);
CREATE FUNCTION submission_fts_trigger() RETURNS trigger AS
$$
BEGIN
new.fts :=
setweight(to_tsvector('pg_catalog.english', new.title), 'A') ||
setweight(to_tsvector('pg_catalog.english', new.selftext), 'B');
return new;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_submission_idx_fts_update
BEFORE INSERT OR UPDATE
ON submission
FOR EACH ROW
EXECUTE FUNCTION submission_fts_trigger();
CREATE INDEX search_idx_fts_idx ON submission USING GIN (fts);
sql query for search
"SELECT * FROM submission, plainto_tsquery('foostring') AS q WHERE (fts @@ q);"
现在虽然它可以工作,但它比 sqlite 解决方案慢 8 倍,这有点奇怪,我本以为会有不同的结果。我也环顾四周,根据一些博客文章,上面的解决方案似乎应该很快。
目前我在 table 中的数据大约有 1500 行。
在 postgresql 中进行一次搜索大约需要 32 毫秒,在 sqlite 中进行一次搜索需要 4 毫秒。
我错过了什么吗?有没有办法在 postgresql 中加快搜索速度?如果我向 table 添加更多数据,sqlite 会变慢吗?
像 elasticsearch 这样的东西会更快吗?
edit explain(analyze,buffers) 的结果是:
Nested Loop (cost=12.31..36.12 rows=7 width=876) (actual time=2.517..2.518 rows=1 loops=1)
Buffers: shared hit=34
-> Function Scan on plainto_tsquery q (cost=0.25..0.26 rows=1 width=32) (actual time=2.472..2.472 rows=1 loops=1)
Buffers: shared hit=29
-> Bitmap Heap Scan on submission (cost=12.06..35.79 rows=7 width=844) (actual time=0.040..0.040 rows=1 loops=1)
Recheck Cond: (fts @@ q.q)
Heap Blocks: exact=1
Buffers: shared hit=5
-> Bitmap Index Scan on search_idx_fts_idx (cost=0.00..12.05 rows=7 width=0) (actual time=0.029..0.029 rows=1 loops=1)
Index Cond: (fts @@ q.q)
Buffers: shared hit=4
Planning:
Buffers: shared hit=188
Execution Time: 2.611 ms
Edit 2 因此,我进行的测量来自调用 select 语句的函数,这对于 sqlite 和 postgresql 都是相同的。多亏了分析器,我可以看到 postgresql 足够快,而且我正在使用的 jdbc 包装器似乎增加了很多开销。
谢谢指点
感谢此处的评论,很明显这不是数据库故障。所以我做了一些挖掘,最后想起我还没有添加连接池,而是为每个数据库请求打开一个新的 SQL 连接。
事实证明,这样做比使用连接池需要多 10 倍的时间。
有了连接池,postgresql 全文搜索速度稍微快一些,我现在的设置大约是 10%。
所以我想做一些全文搜索,查看了如何使用 sqlite 进行搜索,实现了它并认为它很慢。所以我选择了 postgresql,因为我在过去几年一直在使用该数据库。
我有一个非常简单的 table + 触发器和一个索引:
CREATE TABLE submission
(
id TEXT NOT NULL,
subreddit_id TEXT NOT NULL,
author TEXT,
created_utc INTEGER,
title TEXT NOT NULL,
selftext TEXT,
permalink TEXT,
num_comments INTEGER,
score FLOAT,
upvote_ratio FLOAT,
fts TSVECTOR,
UNIQUE (id, subreddit_id)
);
CREATE FUNCTION submission_fts_trigger() RETURNS trigger AS
$$
BEGIN
new.fts :=
setweight(to_tsvector('pg_catalog.english', new.title), 'A') ||
setweight(to_tsvector('pg_catalog.english', new.selftext), 'B');
return new;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_submission_idx_fts_update
BEFORE INSERT OR UPDATE
ON submission
FOR EACH ROW
EXECUTE FUNCTION submission_fts_trigger();
CREATE INDEX search_idx_fts_idx ON submission USING GIN (fts);
sql query for search
"SELECT * FROM submission, plainto_tsquery('foostring') AS q WHERE (fts @@ q);"
现在虽然它可以工作,但它比 sqlite 解决方案慢 8 倍,这有点奇怪,我本以为会有不同的结果。我也环顾四周,根据一些博客文章,上面的解决方案似乎应该很快。 目前我在 table 中的数据大约有 1500 行。
在 postgresql 中进行一次搜索大约需要 32 毫秒,在 sqlite 中进行一次搜索需要 4 毫秒。
我错过了什么吗?有没有办法在 postgresql 中加快搜索速度?如果我向 table 添加更多数据,sqlite 会变慢吗?
像 elasticsearch 这样的东西会更快吗?
edit explain(analyze,buffers) 的结果是:
Nested Loop (cost=12.31..36.12 rows=7 width=876) (actual time=2.517..2.518 rows=1 loops=1)
Buffers: shared hit=34
-> Function Scan on plainto_tsquery q (cost=0.25..0.26 rows=1 width=32) (actual time=2.472..2.472 rows=1 loops=1)
Buffers: shared hit=29
-> Bitmap Heap Scan on submission (cost=12.06..35.79 rows=7 width=844) (actual time=0.040..0.040 rows=1 loops=1)
Recheck Cond: (fts @@ q.q)
Heap Blocks: exact=1
Buffers: shared hit=5
-> Bitmap Index Scan on search_idx_fts_idx (cost=0.00..12.05 rows=7 width=0) (actual time=0.029..0.029 rows=1 loops=1)
Index Cond: (fts @@ q.q)
Buffers: shared hit=4
Planning:
Buffers: shared hit=188
Execution Time: 2.611 ms
Edit 2 因此,我进行的测量来自调用 select 语句的函数,这对于 sqlite 和 postgresql 都是相同的。多亏了分析器,我可以看到 postgresql 足够快,而且我正在使用的 jdbc 包装器似乎增加了很多开销。
谢谢指点
感谢此处的评论,很明显这不是数据库故障。所以我做了一些挖掘,最后想起我还没有添加连接池,而是为每个数据库请求打开一个新的 SQL 连接。
事实证明,这样做比使用连接池需要多 10 倍的时间。
有了连接池,postgresql 全文搜索速度稍微快一些,我现在的设置大约是 10%。