Динамический или столбцовый индекс цветообразователя? - PullRequest
9 голосов
/ 30 октября 2009

Я создаю специальное программное обеспечение для форума для создаваемого сайта, которое включает в себя 2 таблицы (которые имеют отношение к этому вопросу): topics и posts. Сообщение относится к теме, и тема содержит тему, а каждое сообщение содержит тело.

Вот основные структуры таблицы со столбцами, относящимися к моему вопросу:

CREATE TABLE topics (
  id bigserial NOT NULL,
  title varchar(128) NOT NULL,
  created timestamp with time zone NOT NULL default NOW(),
  updated timestamp with time zone NOT NULL default NOW(),
  PRIMARY KEY (id)
);

CREATE TABLE posts (
  id bigserial NOT NULL,
  topic_id bigint NOT NULL REFERENCES topics(id) ON DELETE CASCADE,
  body text NOT NULL,
  created timestamp with time zone NOT NULL default NOW(),
  updated timestamp with time zone NOT NULL default NOW(),
  PRIMARY KEY (id)
);

Вот мои два варианта построения полнотекстовых индексов.

Опция 1: Создание динамических индексов цветов для столбцов заголовка / тела.

CREATE INDEX topics_title_idx ON topics USING gin(to_tsvector(title));
CREATE INDEX posts_body_idx ON posts USING gin(to_tsvector(body));

Вариант 2: Создайте дополнительные столбцы для хранения данных заголовка / тела, выделенных в цветовой форме, и добавьте к ним индексы.

ALTER TABLE topics ADD COLUMN topics_vector tsvector NOT NULL;
CREATE TRIGGER topics_ins BEFORE INSERT OR UPDATE ON topics FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(title_vector, 'pg_catalog.english', title);
CREATE INDEX topics_title_idx ON topics USING gin(title_vector);

ALTER TABLE posts ADD COLUMN posts_vector tsvector NOT NULL;
CREATE TRIGGER posts_ins BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(body_vector, 'pg_catalog.english', body);
CREATE INDEX posts_body_idx ON posts USING gin(body_vector);

Я спорю между ними, так как вариант 1 сэкономит мне место на диске, но обеспечит более медленный поиск, а для варианта 2 потребуется дополнительное дисковое пространство при одновременном ускорении поиска.

Давайте представим, что есть 20 новых тем и 100 новых сообщений в день. Что бы вы выбрали? Что делать, если количество тем / сообщений в день вдвое больше? Пять раз что? Десять раз? Меняется ли ваше решение одного против другого?

Ответы [ 3 ]

6 голосов
/ 30 октября 2009

Использование Опция 1 не сделает ваш поиск более медленным.

Индекс GIN будет использоваться независимо от того, был ли вы создан в конкретном столбце или в вычисленном выражении.

Вам просто нужно изменить синтаксис запроса:

SELECT  *
FROM    posts
WHERE   TO_TSVECTOR('english', title) @@ myquery

в первом случае или

SELECT  *
FROM    posts
WHERE   title_vector @@ myquery

во втором случае.

Вероятно, вы можете сэкономить немного времени при использовании TS_RANK над экземпляром столбца.

5 голосов
/ 30 октября 2009

Давайте представим, что есть 20 новых тем & 100 новых сообщений в день. Которые бы твой выбор? Что делать, если количество тем / сообщений в день вдвое больше? Пять раз что? Десять раз? Ваш решение одного против другого изменения?

Это около 36 000 сообщений в год. Не имеет значения Вероятно, это не имеет значения в десять раз, даже на дешевой машине.

Однако вам может потребоваться третья таблица, содержащая явный tsvector, объединяющий тему и основной текст вместе. Затем вы можете использовать встроенную систему весов и запустить один поиск, чтобы обеспечить поиск, который люди обычно ожидают на форумах и т. Д. Это будет означать написание пользовательских триггеров для обновления вашего tsvector при изменении любой исходной таблицы.

3 голосов
/ 30 октября 2009

Обычно я бы пошел с хранением tsvector в поле, потому что это также даст вам удобный доступ к таким вещам, как headline () и rank ().

...