Модель базы данных для хранения выражений и их появления в тексте

0

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


Изменить: я буду использовать mysql или postgresql + spring templates

  • 0
    Таким образом, вы хотите иметь возможность говорить такие вещи, как «наиболее часто встречающиеся первые 2 буквы были« th », что произошло в общей сложности 5283 раза в 423 словах», и «из первых 2 букв, которые встречались вообще, самое редкое был 'qa'; с него начинается только одно слово? " Сколько текста вы смотрите?
  • 0
    Нет, вхождения самого слова в тексте. Я собираюсь сохранить слова / ключевые слова в соответствии с их 2 начальными буквами (комбинация из 2 букв - 676), каждое слово должно быть связано с количеством его вхождений в тексте, из которого я получаю ключевые слова. таким образом, таблица будет [комбинация букв, среднее число случаев, максимальное количество случаев, минимальное количество случаев]. но есть 676 комбинаций этих букв, и если бы я хотел сделать это с 3 начальными буквами, это было бы 17 000 комбинаций :-), например, одно слово для начальных букв "do" было бы собакой, и было бы своя максимальная / минимальная / средняя
Показать ещё 2 комментария
Теги:
database-design

1 ответ

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. (Хотя указание низкого заполняющего фильтра, например, 60 или около того на word_count, было бы хорошей идеей, так как вы знаете, что он все равно будет несколько искажен для обновлений).

Если ваш ввод на самом деле является парами слов/вхождений, а не просто словами (ваш текст не очень ясен), вы можете вынуть начальную таблицу word_stage и просто скопировать в word_count_stage, или, возможно, вам понадобится начальная table и хотите скопировать значения DISTINCT из этой начальной таблицы в word_count_stage.

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

  • 0
    Это отличное решение, я собираюсь сделать это прямо сейчас. Спасибо
  • 0
    @ lisak ntw, поскольку вы подразумеваете, что будете использовать Java - я кратко упомянул «использовать pgputcopydata ...», чтобы поместить данные в word_stage. В терминах Java это означает создание PGCopyOutputStream для соединения, что вам придется делать самостоятельно, поскольку оно зависит от postgresql. Конечно, вы можете заполнить таблицу, используя стандартные вещи Spring и операторы INSERT, но использование COPY должно быть быстрее.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню