2015-12-29 3 views
0

У меня есть немного блокировки мозга на этом.Отметить все как прочитанные

TLDR; Как эффективно реализовать «метку как прочитанную» для миллионов элементов?

У меня есть случай маркировки всех статей, прочитанных. Десятки тысяч. Решение, которое у меня теперь работает, отлично подходит для небольшого количества статей, но оно очень и очень медленно с большими числами. Это потому, что для каждой прочитанной статьи я заполняю одну таблицу новой строкой. Не имеет значения, сделаю ли я 100 000 вставок в одной транзакции, или я вставляю в select (bla bla bla), это все еще занимает много времени. Мне было интересно переключиться на массивы postgresql, но я не уверен, как это будет работать сотнями тысяч предметов.

Любые предложения, какой будет лучший подход здесь?

У меня есть 3 таблицы:

articles 
- id 
- title 

users 
- id 
- name 

и таблица с отображением какой статьи данного пользователя прочитали.

read_articles 
- article_id - foreign key 
- user_id - foreign key 
+0

массивы postgresql на самом деле связаны списками, сложность n-квадратов будет больно. – Jasen

ответ

1

Почему вы не удалить внешние ключи из read_article таблицы и создать уникальный индекс на обоих столбцах. Это должно ускорить поиск и вставить запросы. Чтобы проверить, прочитана ли статья, вы можете использовать подзапрос в основном запросе и при вставке строки в таблицу вы можете использовать оператор upsert.

Я думаю, что это пустая трата времени и процессора, чтобы связать статьи и идентификатор пользователя с внешними ключами, так как да, вам нужна согласованность, но это не так важно.

+0

Я не уверен, почему вы получили -1, но это действительно самый верный ответ. я заметил, что это занимает много времени, чтобы проверить FKEY ограничение 'Trigger для ограничения reads_article_id_fkey: время = 92356.367 вызовов = 43629 Trigger для ограничения reads_user_id_fkey: время = 717.707 вызовов = 43629 Общее время выполнения: 93651.255 мс (16 строк) ' Итак, я бросил его, и теперь эта вставка вместо 93 секунд занимает 1,5-2 секунды. Если у вас есть идеи, как оптимизировать это дальше, пожалуйста, не стесняйтесь и дайте мне знать! :-) Спасибо! – canto

-1
insert into read_articles 
     (article_id, user_id) 
select id 
,  42 -- User id here 
from article 
+0

К сожалению, как я уже сказал - неважно, сделаю ли я 100 тысяч вставок в одной транзакции, или я вставляю в select (bla bla bla), это все еще требует возраста. – canto

+0

Вы можете добавить к пользователю столбец 'read_until' и обрабатывать все статьи до этой даты как прочитанные. Вы можете периодически чистить записи 'read_article', которые больше не нужны, потому что' read_until' сдвинулся. Или еще проще, предположите, что все статьи старше 21 дня читаются, что значительно сокращает количество статей, которые вы должны вставить. – Andomar

+0

Хм ... Это интересный подход. Тем не менее, я хотел бы сохранить историю, чтобы пользователь мог видеть, что он прочитал. Спасибо за подсказку! :-) Избавление от fkeys значительно ускоряет процесс. – canto

0
insert into read_articles (article_id, user_id) 
select a.id, u.id 
from articles a cross join users u 
+0

К сожалению, как я уже сказал - неважно, сделаю ли я 100 тысяч вставок в одной транзакции, или я вставляю в select (bla bla bla), это все еще требует возраста. – canto

+0

@canto Как и во всех вопросах производительности, необходимо много информации. Вы ничего не предоставили. –

Смежные вопросы