Я занимаюсь статистическим исследованием. Мне нужно хранить слова в соответствии с 2 начальными буквами, что составляет 676 комбинаций, и каждое слово имеет количество вхождений (минимальное, максимальное, среднее) в тексте. Я не уверен, как должна выглядеть модель/схема. Будет много проверки того, было ли ключевое слово уже сохранено. Я ценю ваши предложения.
Изменить: я буду использовать mysql или postgresql + spring templates
Если у вас много миллионов слов, сохранение только их префикса кажется плохим планом.
Чтобы добавить новые данные в таблицу, вы можете просто написать временную таблицу, заполненную входящими словами, а затем просто скомпилировать и объединить их в один конец в конце запуска импорта. То есть, что-то вроде:
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
. (Хотя указание низкого заполняющего фильтра, например, 60 или около того на word_count
, было бы хорошей идеей, так как вы знаете, что он все равно будет несколько искажен для обновлений).
Если ваш ввод на самом деле является парами слов/вхождений, а не просто словами (ваш текст не очень ясен), вы можете вынуть начальную таблицу word_stage
и просто скопировать в word_count_stage
, или, возможно, вам понадобится начальная table и хотите скопировать значения DISTINCT из этой начальной таблицы в word_count_stage
.
Серьезно, я бы попытался использовать все слово в качестве ключа, по крайней мере, изначально - числа, которые вы цитируете, находятся в пределах удобства использования. Также обратите внимание, что описанный выше подход к загрузке может быть легко изменен, чтобы урезать слово до первых двух символов (или преобразовать его в произвольный код памяти любым способом), либо путем преобразования, когда данные перемещаются в word_count_stage
или даже прямо в конце, поместив преобразование в операторы update/insert (хотя вы, возможно, потеряете выгоду от наличия индекса в таблице temp таким образом).