2010-06-06 72 views
0

我做了统计研究中的应用出现。我需要根据2个首字母来存储单词,这是676个组合,每个单词在文本中都有其出现次数(最小,最大,平均)。我不确定模型/模式应该如何。将会有很多检查关键字是否已被保留。我感谢你的建议。数据库模型,用于存储表达及其在文本


编辑:我将使用MySQL或PostgreSQL的春天+模板

+0

所以,你要能说这样的话“中最频繁出现的前两个字母是‘日’,它一共在423个字5283次发生”和“发生在所有的最初2个字母的,最稀有的是'qa';只有一个词以它开头“? 你在看多少文字? – 2010-06-06 02:31:10

+0

不,这个词本身在文本中出现。我将根据它们的2个首字母(两个字母的组合)来保留单词/关键字,每个单词需要将我从中获取关键字的文本中的出现次数关联起来。所以表格应该是[字母组合,平均出现次数,最大出现次数,最小出现次数]。但是这些字母组合中有676个,如果我想用3个首字母做它,它将是17000个组合:-)例如,对于“do”首字母的一个词将是狗,并且它将具有自己的最大/最小/平均 – lisak 2010-06-07 09:50:51

+0

我可以把它与字作为唯一指标只是一个表,但是就不会有那么检查字是否已经存在可能是“不可能的”千行百。我可以使用REPLACE,因为我从中获取关键字的源可以在很多时候为我提供相同的关键字,但始终是相同的值。否则我将不得不在执行SELECT前许多100k次,然后填写表或者捕获重复条目异常而不检查 – lisak 2010-06-07 09:53:59

回答

1

除非你有几百万的话,存储只是它们的前缀似乎是一个不错的计划。

添加新的数据到表中,你可以简单地写一个临时表充满传入的话,然后就聚集在导入运行结束一气呵成在合并这些。也就是说,如下所示:

BEGIN; 
CREATE TEMP TABLE word_stage(word text) ON COMMIT DROP; 
COPY word_stage FROM stdin; 
-- use pgputcopydata to send all the words to the db... 
SET work_mem = 256MB; -- use lots of memory for this aggregate.. 
CREATE TEMP TABLE word_count_stage AS 
    SELECT word, count(*) as occurrences 
    FROM word_stage 
    GROUP BY word; 
-- word should be unique, check that and maybe use this index for merging 
ALTER TABLE word_count_stage ADD PRIMARY KEY(word); 
-- this UPDATE/INSERT pair is not comodification-safe 
LOCK TABLE word_count IN SHARE ROW EXCLUSIVE MODE; 
-- now update the existing words in the main table 
UPDATE word_count 
SET word_count.occurrences = word_count.occurrences + word_count_stage.occurrences, 
    word_count.min_occurrences = least(word_count.occurrences, word_count_stage.occurrences), 
    word_count.max_occurrences = greatest(word_count.occurrences, word_count_stage.occurrences) 
FROM word_count_stage 
WHERE word_count_stage.word = word_count.word; 
-- and add the new words, if any 
INSERT INTO word_count(word, occurrences, min_occurrences, max_occurrences) 
    SELECT word, occurrences, occurrences, occurrences 
    FROM word_count_stage 
    WHERE NOT EXISTS (SELECT 1 FROM word_count WHERE word_count.word = word_count_stage.word); 
END; 

因此,这汇总了一批字的值,然后将它们应用到字数表中。有关于word_stage(word)word_count(word)指数开辟了可能性,如使用如果两个表是大的合并,你不能轻易试图在同一时间更新在主表中的每一行做。更不要说降低word_count中可能产生的垃圾数量。 (尽管在word_count中指定一个60左右的低填充因子会是个好主意,因为你知道它仍然会因为更新而有所不同)。

如果输入实际上是字/事件对的,而不是仅仅字(文字不是很清楚),那么你可以拿出最初的word_stage表,只是复制到word_count_stage,或者你需要一个初始表,并希望将DISTINCT值从该初始表复制到word_count_stage

说真的,我想尝试使用整个单词的一个关键至少initially-你引用的数字是很好的可用性的范围内。另外请注意,上面概述的加载方法可以很容易地修改,以便很容易地将一个单词截断为前两个字符(或者以任意方式将其转换为内存键),或者通过在数据移动到word_count_stage或甚至在最后通过将转换放入更新/插入语句中(尽管您可能会失去在临时表上使用索引的好处)。

+0

这是一个很好的解决方案,我是现在就这样做。谢谢 – lisak 2010-06-09 10:46:47

+0

@lisak ntw,因为你暗示你会使用Java-我简单地提到“使用pgputcopydata ...”将数据放入word_stage中。用Java语言来转换为在连接上创建一个PGCopyOutputStream--你必须自己做,因为它是特定于PostgreSQL的。您当然可以使用标准的Spring stuff和INSERT语句填充表,但使用COPY应该更快。 – araqnid 2010-06-10 13:53:24

相关问题