有一张桌子:
doc_id(integer)-value(integer)
大约100.000 doc_id和27.000.000行。
此表上的多数查询 - 搜索类似于当前文档的文档:
select 10 documents with maximum of
(count common to current document value)/(count ov values in document).
现在我们使用PostgreSQL。表重(带指数)~1.5 GB。平均查询时间~0.5秒 - 这是高。而且,就我而言,随着数据库的增长,这一时间将呈指数增长。
我是否应该将所有这些转移到NoSQL基础,如果是,那该什么?
QUERY:
EXPLAIN ANALYZE
SELECT D.doc_id as doc_id,
(count(D.doc_crc32) *1.0 / testing.get_count_by_doc_id(D.doc_id))::real as avg_doc
FROM testing.text_attachment D
WHERE D.doc_id !=29758 -- 29758 - is random id
AND D.doc_crc32 IN (select testing.get_crc32_rows_by_doc_id(29758)) -- get_crc32... is IMMUTABLE
GROUP BY D.doc_id
ORDER BY avg_doc DESC
LIMIT 10
Limit (cost=95.23..95.26 rows=10 width=8) (actual time=1849.601..1849.641 rows=10 loops=1)
-> Sort (cost=95.23..95.28 rows=20 width=8) (actual time=1849.597..1849.609 rows=10 loops=1)
Sort Key: (((((count(d.doc_crc32))::numeric * 1.0) / (testing.get_count_by_doc_id(d.doc_id))::numeric))::real)
Sort Method: top-N heapsort Memory: 25kB
-> HashAggregate (cost=89.30..94.80 rows=20 width=8) (actual time=1211.835..1847.578 rows=876 loops=1)
-> Nested Loop (cost=0.27..89.20 rows=20 width=8) (actual time=7.826..928.234 rows=167771 loops=1)
-> HashAggregate (cost=0.27..0.28 rows=1 width=4) (actual time=7.789..11.141 rows=1863 loops=1)
-> Result (cost=0.00..0.26 rows=1 width=0) (actual time=0.130..4.502 rows=1869 loops=1)
-> Index Scan using crc32_idx on text_attachment d (cost=0.00..88.67 rows=20 width=8) (actual time=0.022..0.236 rows=90 loops=1863)
Index Cond: (d.doc_crc32 = (testing.get_crc32_rows_by_doc_id(29758)))
Filter: (d.doc_id <> 29758)
Total runtime: 1849.753 ms
(12 rows)
答案 0 :(得分:3)
1.5 GByte什么都没有。从公羊服务。构建一个可以帮助您搜索的数据结构。
答案 1 :(得分:1)
我不认为你的主要问题是你正在使用的那种数据库,但事实上你实际上并没有为你搜索的内容提供“索引”:文档之间的相似性。
我的建议是确定哪一个10个文档与100.000 doc_ids中的每个文档类似,缓存结果如下所示:
doc_id(integer)-similar_doc(integer)-score(integer)
您将在每个文档中插入10行,每个文档代表10个最佳匹配项。您将获得400.000行,您可以通过索引直接访问这些行,这应该将搜索时间缩短为O(log n)(取决于索引实现)。
然后,在每次插入或删除文档(或其中一个值)时,您将遍历文档并相应地更新新表。
e.g。插入新文档时: 对于表中已有的每个文件
答案 2 :(得分:0)
首先,问题是0.5秒?您是否已经优化了查询,数据模型和配置设置?如果没有,您仍然可以获得更好的性能。性能是一种选择。
除了速度之外,还有功能,这就是你将要放松的东西。
===
如何将函数推送到JOIN:
EXPLAIN ANALYZE
SELECT
D.doc_id as doc_id,
(count(D.doc_crc32) *1.0 / testing.get_count_by_doc_id(D.doc_id))::real as avg_doc
FROM
testing.text_attachment D
JOIN (SELECT testing.get_crc32_rows_by_doc_id(29758) AS r) AS crc ON D.doc_crc32 = r
WHERE
D.doc_id <> 29758
GROUP BY D.doc_id
ORDER BY avg_doc DESC
LIMIT 10
答案 3 :(得分:0)
如果你从PostgreSQL中获得了糟糕的性能,那么一个好的开始就是调整PostgreSQL,你的查询以及你的数据模型。像这样的查询应该可以在这么小的表上更快地提供服务。