Если у объекта 10 уникальных лексем, у меня добавиться десять записей.

Судя по описанию GIN - у них тоже.

Если я правильно понимаю - нет. Смотри сюда:

http://archives.postgresql.org/pgsql-hackers/2006-04/msg00960.php

"Gin is consists of a B-tree constructed over entries (ET, entries tree), where entry is an element of indexed value ( element of array, lexeme for tsvector) and where each tuple in the leaf pages is either pointer to B-tree over item pointers (PT, posting tree), or list of item pointers (PL, posting list) if tuple is small enough."

и дальше по тексту "There is no delete operation for ET. The reason for this, is that from our experience, a set of unique words of a whole collection changed very rare."

При добавлении 10 новых документов изменяется только конкретный "листик" из бинарного дерева, но ничего не добавляется (если только это не новая лексема в словаре).

То-есть, если говорить грубо, то это было бы что-то такое на нормальном SQL

  SELECT intersect(i.doc_ids)
  FROM my_index_table i
  WHERE i.word IN (...)

где intersect(<list>):<list> - аггрегатная ф-ция, которая для каждого передаваемого ей списка считает пересечение этого списка с уже аггрегированым результатом.

Мы могли бы использовать intersect(blob):blob, если договорится, что в блобах хранятся, например, 64-битные идентификаторы. Но у нас нет аггрегатных UDF...

Теперь мне нужно выбрать объекты у которых есть 3 лексемы.

При подходе описаном выше достаточно одного прохода по индексу.

Я, кстати, такое делал для spatial-индекса. Листья дерева хранил в блобах (ID документов), пересечение делал на клиенте (предварительно отобрав на сервере все подходящие листья). В приложении поиск шел одновременно по моему spatial-индексу, полнотекстовому индексу на lucene и резалт-сету обычного поиска в базе по другим полям. Работало хорошо, но у меня были (если правильно помню) только где-то 100-200 тыс записей - инфо о кафешках, ресторанах, и др. организация с текстом (меню, например), геогр. координатами, и прочей инфо.

Роман

Ответить