2010-06-06 30 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

相關問題