У меня есть таблица соединений со следующей структурой:
CREATE TABLE adjectives_friends
(
adjective_id integer,
friend_id integer
)
WITH (
OIDS=FALSE
);
ALTER TABLE adjectives_friends
OWNER TO rails;
CREATE UNIQUE INDEX index_adjectives_friends_on_adjective_id_and_friend_id
ON adjectives_friends
USING btree
(adjective_id , friend_id );
CREATE UNIQUE INDEX index_adjectives_friends_on_friend_id_and_adjective_id
ON adjectives_friends
USING btree
(friend_id , adjective_id );
ALTER TABLE adjectives_friends CLUSTER ON index_adjectives_friends_on_friend_id_and_adjective_id;
Эта таблица содержит около 50 миллионов записей.
Таблица прилагательных - это справочная таблица из ~ 150 записей. Я хотел бы найти друга, который наиболее точно соответствует списку прилагательных. Предположим, что максимальное количество прилагательных, которые есть у друга, равно 10. Итак, я попробовал этот запрос:
SELECT count(friend_id) count, friend_id
FROM adjectives_friends
where adjective_id in (1,2,3,4,5,6,7,8,9,10)
group by friend_id
order by count desc
limit 100
Это займет около 10 секунд на моем компьютере разработчика с планом запроса
"Limit (cost=831652.00..831652.25 rows=100 width=4)"
" -> Sort (cost=831652.00..831888.59 rows=94634 width=4)"
" Sort Key: (count(friend_id))"
" -> GroupAggregate (cost=804185.31..828035.16 rows=94634 width=4)"
" -> Sort (cost=804185.31..811819.81 rows=3053801 width=4)"
" Sort Key: friend_id"
" -> Bitmap Heap Scan on adjectives_friends (cost=85958.72..350003.24 rows=3053801 width=4)"
" Recheck Cond: (adjective_id = ANY ('{1,2,3,4,5,6,7,8,9,10}'::integer[]))"
" -> Bitmap Index Scan on index_adjectives_friends_on_adjective_id_and_friend_id (cost=0.00..85195.26 rows=3053801 width=0)"
" Index Cond: (adjective_id = ANY ('{1,2,3,4,5,6,7,8,9,10}'::integer[]))"
Заказ убивает меня, но я не знаю, как избежать этого. Количество не может быть предварительно вычислено, потому что прилагательные, которые будут выбраны, являются абсолютно произвольными, и есть> 150, выбирают 10 комбинаций. Прямо сейчас, я думаю, что лучший вариант - собрать 100 лучших результатов при создании друзей, сохранить результаты, а затем обновлять их каждые n интервалов времени. Это было бы приемлемо, так как ожидается, что прилагательные будут переключаться так часто, и я не могу получить 100 лучших результатов. Но если бы я мог увеличить скорость запроса до 1-2 секунд, это не было бы необходимым. Есть предложения?