在我的系统中Users
可以添加/编辑/查看Customers
。我想添加一个功能,允许用户看到“最近查看的客户”。这将向他们展示他们见过的最后20个客户(包括添加/编辑)。
用户会在不同网页之间跳过时经常查看客户,这需要非常高效。我想在会话中坚持这一点,因此需要将其保存到数据库中。大约有16,000名用户和600,000名客户。
这就是我所想的设计。
创建一个新表:
(UserId, CustomerId, DateViewed)
(UserId, CustomerId)
UserId
和CustomerId
DateViewed
列仅存在以允许记录的排序创建一个PL / SQL过程,其参数为UserId
和CustomerId
,负责存储用户查看客户的信息。在PL / SQL过程中,我会:
MERGE
插入或更新具有给定UserId
和CustomerId
设置DateViewed
至SYSDATE
row_number()
>的所有行。 20 “最近查看的客户”页面将成为此新表和客户表之间的基本联接,由DateViewed排序,并且为了以防情况限制为20条记录。无需在任何索引中包含DateViewed,因为它只有20行排序。
比如说,每月一次,删除DateViewed超过一年的所有记录。这将是一次全面扫描。级联从客户和用户删除到新表。
是否有人有改进建议或其他值得分析的想法?
(我的另一个想法是将具有20列的表进行非规范化,以便从CustomerId1向下调整不同的CustomerIds和shuffle值 - > CustomerId2 - > CustomerId3。这将需要不同的更新,具体取决于CustomerId已经出现在哪里清单。)
答案 0 :(得分:2)
我相信你已经彻底仔细考虑了这个问题。
我建议您尝试的一件事是推迟修剪21(以及之后)最近查看的客户的用户。如果你这样做,你必须在选择查询中加入一个TOP 20.
完成修剪操作需要一些时间(无论是对每个新视图还是以后完成)。从20多个名单中挑选前20名也会有一些增量时间。
根据客户添加/编辑/查看的确切频率,可能每次插入记录时修剪比排序和选择TOP 20更昂贵。您可以将修剪作为预定的后台任务执行,比如每小时一次,甚至每天一次。
根据实际使用情况,性能也可能不存在问题,您应该优化可维护性,在这种情况下,您应该使用最少的代码执行最简单的操作。
关于您的其他想法(20个非规范化列):This is not recommended!
答案 1 :(得分:1)
我同意列和主键;我不同意索引策略。
您要优化的查询是:
select customer_id, rn
from (select customer_id, rownum as rn
from user_viewed_customer
where user_id = :p_user_id
order by date_viewed desc)
where rn <= 20;
该查询的最佳情况是仅索引:(user_id, date_viewed desc, customer_id)
。将表进行索引组织几乎没有增加,user_id
和customer_id
上的单列索引也是如此 - 由于多列索引,因此不需要user_id
上的索引,并且customer_id
索引仅支持级联删除。我很惊讶您实际上能够删除客户;当你这样做的时候,其余的历史数据会发生什么?
要考虑的另一个策略是上面的表格是否真的应该是一个表格和物化视图;每个user_id
和customer_id
组合的表格,以及提交物化视图,将较大的表格提炼为每个用户的前20名。如果上面较大的表和查询的性能不足,我只会进行优化。