帮助为项目选择NoSQL数据库

时间:2010-03-21 07:46:16

标签: sql postgresql nosql key-value-store

有一张桌子:

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)

4 个答案:

答案 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。插入新文档时: 对于表中已有的每个文件

  1. 您计算其匹配分数和
  2. 如果分数高于新表中缓存的类似文档的最低分数,则交换新插入文档的similar_doc和分数

答案 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,你的查询以及你的数据模型。像这样的查询应该可以在这么小的表上更快地提供服务。