我的数据库中有一个名为Token的表,表示文本标记化。
每一行都有文本块,句子和位置(用于标识令牌来自的文本)和逻辑字段(如文本,类别,图表等)等属性。
我想知道的是迭代所有标记以查找模式并执行某些操作。例如,将具有类别名称的两个相邻令牌合并为一个(在此之后,重置位置)。我想我需要某种清单
最好的方法是什么?使用SQL查询查找模式或迭代表中的所有标记。我认为查询会很复杂,也许,迭代作为列表将更简单,但我不知道是哪种方式(例如,检索到Java列表或使用我可以迭代和执行的语言在数据库上改变了。)
对于这个问题没有被关闭,我想知道的是最推荐的方法是什么?我正在使用Java,但如果其他语言更好,没问题,我想我需要使用R来做一些统计计算。
编辑:表格很大,数百万行,无法在内存中加载。
答案 0 :(得分:3)
如果您正在使用小表或证明合并策略,那么只需设置一个查找所有候选重复行的查询,并将相关列转储到表中。然后在文本编辑器或电子表格中查看该表,以查看您的重复假设是否正确。
请记住,只要您尝试将两行合并为一行,就会删除数据。最糟糕的情况是,您可以将所有行合并为一个。谨慎行事!
答案 1 :(得分:2)
这不是最优化的方法,但它是一种允许您轻松编写代码的设计。
编写一个表示表中一行的实体类。
编写一个工厂方法,允许您获取给定行id的实体对象,即使用指定行中的值创建实体类对象的方法。
编写删除并将给定行对象插入表中的方法。
写一个行计数方法。
现在,您可以尝试使用Java代码迭代表。请记住,如果在两行之间合并,则需要正确调整下一个索引。
此方法允许您使用小内存,但您将使用大量查询来创建行。
该概念与ORM(对象关系映射)非常相似或相同。如果您知道如何使用hibernate或其他ORM,那么请尝试这些库。
答案 2 :(得分:2)
这是一项工程决策,主要基于您要维护的语料库的大小,以及您希望对其执行的操作类型。
如果尺寸大于“适合编辑器的尺寸”,则需要某种数据库。那可能是也可能不是SQL数据库。但是还有代码部分:如果你想对数据执行非平凡的操作,你可能需要一个真正的编程语言(可能是任何东西:C,Java,Python。任何东西都可以)。在这种情况下,与数据库的通信将成为瓶颈:您需要生成产生适合应用程序内存的结果的查询。 SQL足够强大,可以表示和存储N-gram并对它们进行一些计算,但这大概就是你要得到的。在任何情况下,数据库都必须完全规范化,这将使非DBA更难理解。
我自己的玩具项目http://sourceforge.net/projects/wakkerbot/使用了混合方法:
[在另一个生命中,我可能会做更多的规范化,并在数据库中存储N-gram或树。这可能会导致性能下降到每秒几个生成的句子。它现在大约是4000 /秒]
我的直觉是,你想要的更像是一个“语言工作台”,而不是一个有效地完成一项任务的程序(如wakkerbot)。在任何情况下,您都需要更多地标准化:将标记存储为{tokennumber,tokentext}并仅通过数字引用它们。基本上,文本只是包含一堆标记号的表(或数组)。 N-gram只是几个令牌数+相应的系数。
答案 3 :(得分:1)
IMO将所有内容加载到Java并在那里进行操作以避免不断重新查询数据库会更容易,也可能更快。
还有一些非常强大的Java和统计数据库;在你确定你所需要的东西不可用(或太慢)之前,我不会将其解雇。
答案 4 :(得分:1)
这听起来像是在设计一个文本搜索引擎。你应该先看看pgsql的全文搜索引擎是否适合你。
如果你没有全文搜索,那么将pl加载到pgsql并学习驱动它可能是最快速,最有效的解决方案。它允许您将所有这些工作放在一些经过深思熟虑的R行中,并在db中最接近数据访问的所有内容。避免这样一个计划的唯一时间是它会使数据库服务器非常困难,比如将数据集保存在内存中并在其上启动单个cpu核心。然后可以在应用程序端进行操作。
无论您是否使用pl / R,访问游标中的大型数据集,它是获得单个或更小行的子集的最有效方法。如果您使用带有where子句的select来处理每个要处理的事物,那么您不必一次将所有这些行保存在内存中。您可以在执行平均值等操作时抓取并丢弃部分结果集。
在这里考虑规模。如果您有一个5 TB的数据库,您将如何以最快的速度访问它?一个糟糕的扩展解决方案会回来咬你,即使它只访问1%的数据集。如果你今天已经开始使用一个非常大的数据集,它会随着时间的推移而变得更糟。