用于存储具有多元素搜索的ngrams的数据库模式

时间:2013-12-14 13:51:26

标签: sql database database-design n-gram

我想在磁盘上存储大量的ngram,以便我可以对它执行以下查询:

  • 获取所有ngrams
  • 获取特定大小的所有ngrams
  • 获取包含任何位置(子集)
  • 中所有这些给定元素的所有ngrams
  • 获取具有这些位置(模板)
  • 中这些给定元素的特定大小的所有ngrams

第三点的一个例子是所有包含'a','b'和'c'的ngram,它们产生ngrams,如(a,b,c),(b,c,a),(x,a ,z,b,c)等。

第四点的一个例子是模板后面的所有ngrams(a,*,*,b),它们产生ngrams,如(a,x,y,b),(a,a,a,b),等

目前我将它们存储在数据库表中,并为ngram的每个元素分别使用一个字段,但这似乎不是搜索包含任何顺序和位置的给定元素的ngram的最佳选择。为了搜索包含“a”,“b”和“c”的3grams,我使用以下SQL'where'子句:

WHERE
     (ele0 = 'a' OR ele1 = 'a' OR ele2 = 'a') AND
     (ele0 = 'b' OR ele1 = 'b' OR ele2 = 'b') AND
     (ele0 = 'c' OR ele1 = 'c' OR ele2 = 'c')

这根本不能很好地扩展。有没有更好的方法来构建数据并进行查询?

1 个答案:

答案 0 :(得分:2)

您没有指定“大号”是什么。我不能想到一种方法来支持使用标准SQL优化方法所需的所有操作。在某些数据库中,全文支持可能有所帮助。

如果你想使用SQL(作为持久存储非常合理),我建议你只使用字符串。换句话说,ngram是一个字符串。

您的查询如下:

select *
from ngrams;

select *
from ngrams
where len(ngram) = XXX

select *
from ngrams
where ngram like '%a%' and ngram like '%b%' and ngram like '%c%';

select *
from ngrams
where ngram like 'a__b';

然后,您可以增强此结构,使其对某些查询更有效。例如,如果要优化查询以获取长度,则添加length列并对其进行索引(除非您有很多不同的长度,否则这将不会非常有用)。要优化第三种类型的查询,请添加一个按字母顺序排列元素的新列(因此,“CBA”也会有一列“ABC”)。对此的索引将有助于查询第三种类型。

编辑(回应评论):

我一直认为n-gram首先引用单个字符,但Wikipedia表示它们是任何项目的顺序集。

您可以使用上述架构轻松处理“单词”,只需引入一个不是任何单词中允许字符的分隔符,例如'|'分隔符。因此,n-gram“ABC”将存储为“| A | B | C |”:

select *
from ngrams;

select *
from ngrams
where ngramLen = XXX

select *
from ngrams
where ngram like '%|a|%' and ngram like '%|b|%' and ngram like '%|c|%';

select *
from ngrams
where ngram like |a|%|b|' and ngramLen = 4;

在这种情况下,您需要一个具有元素数量的单独字段,因为您无法使用长度函数轻松计算。

考虑到你正在考虑拥有数百万的ngram,你会遇到一些挑战。用文字来说,这可能占用高达千兆字节的内存。为了提高性能,您需要将表放入内存中。这些操作非常适合并行数据库,因此该过程将顺利扩展。事实上,使用数据库的一个优点是,您可以简单地在问题上投入更多内存/磁盘/处理器,并且您将获得更好的性能。