我正在开发一个使用贝叶斯过滤器的rss提要阅读器来过滤枯燥的博客帖子。
Stream表用作FIFO缓冲区,webapp将从中使用“条目”。我用它来存储条目,用户和贝叶斯过滤器分类之间的临时关系。
用户将条目标记为已读取后,将其添加到元数据表中(以便不向用户显示已读取的内容),并从流表中删除。每隔三分钟,后台进程将使用新条目重新填充Stream表(即,在检查rss提要更新后守护进程添加新条目时)。
问题:我提出的查询是hella slow。更重要的是,Stream表一次只需要保存一百个未读条目;它可以减少重复,加快处理速度,并为我显示条目提供一些灵活性。
查询(3600个没有索引的项目大约需要9秒):
insert into stream (entry_id, user_id)
select entries.id, subscriptions_users.user_id
from entries
inner join subscriptions_users on subscriptions_users.subscription_id = entries.subscription_id
where subscriptions_users.user_id = 1
and entries.id not in (select entry_id
from metadata
where metadata.user_id = 1)
and entries.id not in (select entry_id
from stream where user_id = 1);
查询说明:将用户尚未阅读的用户订阅列表(subscriptions_users)中的所有条目插入流中(即元数据中不存在),以及流中尚不存在的条目。
尝试的解决方案:在最后添加限制100会大大加快查询速度,但是一旦重复执行,将继续添加一组不同的100个条目,这些条目在表中不存在(每个成功的查询需要更长时间) 。
这很接近但不完全是我想做的事。
有没有人有任何建议(nosql?)或者知道更有效的撰写查询的方式?
答案 0 :(得分:1)
查询(大约需要9秒钟 3600项没有索引的项目):
然后我会尝试从一些索引开始......
OR LEFT JOIN NULL (和索引)
SELECT *
FROM TABLEA A LEFT JOIN
TABLEB B ON A.ID = B. ID
WHERE B.ID IS NULL
答案 1 :(得分:1)
使用:
INSERT INTO STREAM
(entry_id, user_id)
SELECT e.id,
su.user_id
FROM ENTRIES e
JOIN SUBSCRIPTIONS_USERS su ON su.subscription_id = e.subscription_id
AND su.user_id = 1
LEFT JOIN METADATA md ON md.entry_id = e.id
AND md.user_id = 1
LEFT JOIN STREAM s ON s.entry_id = e.id
AND s.user_id = 1
WHERE md.entry_id IS NULL
AND s.entry_id IS NULL
在MySQL中,LEFT JOIN/IS NULL
是获取一个表中存在的数据的最有效方法,而不是另一个表中存在的数据。 Reference link
在查看索引之前检查查询性能。
在Postgres中:
NOT IN
NOT EXISTS
LEFT JOIN / IS NULL
... are equivalent
答案 2 :(得分:0)
优化选择的一种方法是用连接替换子查询。
类似的东西:
select entries.id, subscriptions_users.user_id
from entries
inner join subscriptions_users on subscriptions_users.subscription_id = entries.subscription_id
left join metadata md on (user_id,entry_id)
left join stream str on (user_id, entry_id)
where subscriptions_users.user_id = 1 and where md.user_id is null and str.user_id is null;
您必须确保左连接的连接条件正确。我不确定你的确切架构是什么,所以我不能。
此外,添加索引也会有所帮助。