Модель базы данных для хранения выражений и их появления в тексте - PullRequest
0 голосов
/ 06 июня 2010

Я делаю приложение для статистических исследований. Мне нужно хранить слова в соответствии с 2 начальными буквами, что составляет 676 комбинаций, и каждое слово имеет количество вхождений (минимальное, максимальное, среднее) в тексте. Я не уверен, как должна выглядеть модель / схема. Будет много проверок, сохранилось ли ключевое слово. Я ценю ваши предложения.


Редактировать: я буду использовать шаблоны mysql или postgresql + spring

1 Ответ

1 голос
/ 09 июня 2010

Если у вас нет миллионов слов, хранение только их префикса кажется плохим планом.

Для добавления новых данных в таблицу вы можете просто написать временную таблицу, полную входящих слов, а затем просто объединить и объединить их за один раз в конце цикла импорта. То есть что-то вроде:

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, или, возможно, вам понадобится начальная таблицу и хотите скопировать значения DISTINCT из этой исходной таблицы в word_count_stage.

Серьезно, я бы попробовал использовать все слово в качестве ключа хотя бы на начальном этапе - числа, которые вы цитируете, находятся в пределах юзабилити. Также обратите внимание, что описанный выше подход к загрузке может быть легко изменен, чтобы довольно просто усечь слово до первых двух символов (или преобразовать его в ключ памяти любым произвольным образом), либо путем преобразования по мере перемещения данных в word_count_stage или даже в самом конце, поместив преобразование в операторы обновления / вставки (хотя вы потенциально потеряете преимущество, если таким способом будет иметь индекс для временной таблицы).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...