0

我想在数据库中保存每个客户按工作日和小时进入网站的次数。这意味着对于每个客户,我将拥有 24 * 7 的值,这些值将不断更新,以反映客户访问次数最多的高峰时段。我已经看到了明显的建议Database structure for holding statistics by day, week, month, year to create a new line for each entry and than use the data, it won't work, we have 数百万行,我需要峰值每个客户可用的时间。此外,为每个客户创建 168 列看起来有点极端。有什么建议么?

4

2 回答 2

0

可能需要进行现实检查。

我将拥有 24 * 7 的值,这些值将不断更新,以反映客户访问次数最多的高峰时段。

这是假设您每天存储 24 个条目,即客户端未显示的条目。除非您的客户是一家公司,否则人们会睡觉。

为每个入口创建一个新行而不是使用数据,它不起作用,我们有数百万行

所以?30 年前,表中的数百万行并不是问题。今天绝对不是问题。是的,它可能无法在 20 年前的台式机上运行 - 但在具有半 tb 内存和适当磁盘布局的中型服务器上,您可以存储数百 GB 的数据并快速处理它们。

此外,为每个客户创建 168 列看起来有点极端。

这也是愚蠢的。我的意思是愚蠢。看 - 问题是虽然您(和您的应用程序)可以使用它,但您很快就会发现,如果您尝试将数据加载到报告工具中并查找特定小时的所有行 - 您生活在一个痛苦的世界。每个条目一行是关系数据模型所建议的。其他任何东西要么是聪明的(对于一个非常有限的用例),要么是证明工具非常快地遵循关系定理,并且你生活在一个非常痛苦的代码世界中。

并不是说它不会发生。我见过人们为每张发票写一个新表(所以发票详细信息表不会太长)......

每个入口有一个条目,您可以按星期几分组,按小时汇总 - 每行有 168 个字段,您不能轻易做到。

通常:这是 2020 年。中端台式机具有 64GB 内存。中端服务器有 1 TB 或 2 TB。SSD 存储使数据库能够轻松快速地处理数百 GB 的数据——这在硬盘时代是非常痛苦的。26 年前,在我的第一个商业级数据库项目中,数百万行是个笑话。今天,数百亿是小变化。

于 2020-09-05T19:06:51.247 回答
0

这是一个表结构(类似于我见过的实现),它将汇总统计信息分离为周、日期(或天)和小时表,并将主键与外键关系连接起来。它不是将一天中的不同时间存储为列(在 rdbms 中不推荐),而是将它们存储在行中。可以根据需要使用适当的索引和分区来处理每天(或每小时)数百万次访问。

像这样的东西

DDL

create table dbo.visitor_events(
    v_id       int identity(1,1) primary key not null,
    client_id   int not null references clients(client_id),
    visit_dt    datetime2(7) not null default sysutcdatetime());

create table dbo.visitor_event_weeks(
    vsw_id       int identity(1,1) primary key not null,
    client_id   int not null references clients(client_id),
    visit_wk    int not null,
    visits      int not null);

create table dbo.visitor_event_dates(
    vsd_id      int identity(1,1) primary key not null,
    client_id   int not null references clients(client_id),
    vsw_id      int not null references visitor_event_weeks(vsw_id),
    visit_wk    int not null,
    visit_dt    datetime not null,
    visits      int not null);

create table dbo.visitor_event_hours(
    vsh_id       int identity(1,1) primary key not null,
    client_id   int not null references clients(client_id),
    vsd_id      int not null references visitor_event_dates(vsd_id),
    visit_hr    datetime not null,
    visits      int not null);

变量

变量和插入/更新语句(会因最适合 OP 而异)

declare 
  @client_id          int=123,
  @visit_dt           datetime2(7)=sysutcdatetime();
declare
  @v_id               int;
declare   
  @vsw                table(vsw_id      int unique not null);
declare   
  @vsd                table(vse_id      int unique not null);

/* Insert a visit */
insert dbo.visitor_events(client_id, visit_dt) values
(@client_id, @visit_dt);
select @v_id=scope_identity();

/* Insert/update a visit week */
update dbo.visitor_event_weeks
set visits=visits+1
output inserted.vsw_id into @vsw
where client_id=@client_id
      and visit_wk=datediff(wk, 0, @visit_dt);
if @@rowcount>0
    begin
        insert dbo.visitor_event_weeks(client_id, visit_wk, visits) 
        output inserted.vsw_id into @vsw
        values (@client_id, datediff(wk, 0, @visit_dt), 1);
    end

/* Insert a visit date */
update dbo.visitor_event_dates
set visits=visits+1
output inserted.vsd_id into @vsd
where client_id=@client_id
      and vsw_id=(select top 1 vsw_id from @vsw)
      and visit_dt=cast(@visit_dt as date);
if @@rowcount>0
    begin
        insert dbo.visitor_event_dates(client_id, vsw_id, visit_dt, visits) 
        output inserted.vsd_id into @vsd
        values (@client_id, (select top 1 vsw_id from @vsw), cast(@visit_dt as date), 1);
    end

/* Insert a visit date hour */
update dbo.visitor_event_dates
set visits=visits+1
output inserted.vsd_id into @vsd
where client_id=@client_id
      and visit_dt=cast(@visit_dt as date);
if @@rowcount>0
    begin
        insert dbo.visitor_event_hours(client_id, vsd_id, visit_dt, visits) 
        output inserted.vsd_id into @vsd
        values (@client_id, (select top 1 vsw_id from @vsw), cast(@visit_dt as date), 1);
    end
于 2020-09-05T19:49:53.247 回答