建议 table 按工作日和时间统计节省访客的方案
Suggested table scheme for saving visitors by week days and hours statistics
我想在数据库中保存每个客户在工作日和小时内进入网站的次数。这意味着对于每个客户,我将拥有 24 * 7 的值,这些值将不断更新以反映客户访问次数最多的高峰时段。
我看到明显的建议 Database structure for holding statistics by day, week, month, year 为每个入口创建一条新线路而不是使用数据,它不会工作,我们有数百万条线路,我需要每个客户的高峰时段可用。
此外,为每个客户端创建 168 列看起来有点极端。
有什么建议吗?
可能需要进行现实检查。
I will have 24 * 7 values that will be constantly updating to reflect the peak hour with
the most visits for the client.
这是假设您每天存储 24 个条目,即客户端未显示的条目。除非你的客户是公司,否则人们会睡觉。
to create a new line for each entrance and than use the data, it won't work, we have
millions of lines
所以呢? table 中的数百万行在 30 年前不是问题。今天绝对不是问题。是的,它可能不会 运行 在 20 年前的台式机上 - 但在具有半 TB 内存和适当磁盘布局的体面的中型服务器上,您可以存储数百 GB 的数据并快速处理它们。
Also, creating 168 columns for each clients looks a little extreme.
也是傻逼。我的意思是愚蠢。看 - 问题是虽然您(和您的应用程序)可以使用它,但您很快就会发现,如果您尝试加载数据,即加载到报告工具中并找到特定时间的所有行 - 您生活在痛苦的世界。每个条目一行是关系数据模型所建议的。其他任何东西要么是 SMART(对于非常有限的用例),要么证明工具非常快地遵循关系定理,而你生活在一个充满痛苦代码的世界中。
并不是说它不会发生。我看到有人为每写一张发票写一个新的 table(所以发票详细信息 table 不会太长)...
每个入口一个条目,您可以按星期几组成一个组,按房屋聚合 - 每行 168 个字段,这不容易。
总的来说:这是 2020 年。中档台式机有 64gb 内存。中档服务器有 1 TB 或 2 TB。 SSD 存储使数据库可以轻松快速地处理数百 GB 的数据——这在硬盘时代是非常痛苦的。数百万行是 26 年前我在第一个商业级数据库项目中的一个笑话。今天,数十亿只是零钱。
这是一个 table 结构(类似于我看到的实现的结构),它将摘要统计信息分为周、日期(或天)和小时 tables 与主要连接外键关系的键。它不是将一天中的不同时间存储为列(在 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);
变量
变量和 insert/update 语句(根据最适合 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
我想在数据库中保存每个客户在工作日和小时内进入网站的次数。这意味着对于每个客户,我将拥有 24 * 7 的值,这些值将不断更新以反映客户访问次数最多的高峰时段。 我看到明显的建议 Database structure for holding statistics by day, week, month, year 为每个入口创建一条新线路而不是使用数据,它不会工作,我们有数百万条线路,我需要每个客户的高峰时段可用。 此外,为每个客户端创建 168 列看起来有点极端。 有什么建议吗?
可能需要进行现实检查。
I will have 24 * 7 values that will be constantly updating to reflect the peak hour with the most visits for the client.
这是假设您每天存储 24 个条目,即客户端未显示的条目。除非你的客户是公司,否则人们会睡觉。
to create a new line for each entrance and than use the data, it won't work, we have millions of lines
所以呢? table 中的数百万行在 30 年前不是问题。今天绝对不是问题。是的,它可能不会 运行 在 20 年前的台式机上 - 但在具有半 TB 内存和适当磁盘布局的体面的中型服务器上,您可以存储数百 GB 的数据并快速处理它们。
Also, creating 168 columns for each clients looks a little extreme.
也是傻逼。我的意思是愚蠢。看 - 问题是虽然您(和您的应用程序)可以使用它,但您很快就会发现,如果您尝试加载数据,即加载到报告工具中并找到特定时间的所有行 - 您生活在痛苦的世界。每个条目一行是关系数据模型所建议的。其他任何东西要么是 SMART(对于非常有限的用例),要么证明工具非常快地遵循关系定理,而你生活在一个充满痛苦代码的世界中。
并不是说它不会发生。我看到有人为每写一张发票写一个新的 table(所以发票详细信息 table 不会太长)...
每个入口一个条目,您可以按星期几组成一个组,按房屋聚合 - 每行 168 个字段,这不容易。
总的来说:这是 2020 年。中档台式机有 64gb 内存。中档服务器有 1 TB 或 2 TB。 SSD 存储使数据库可以轻松快速地处理数百 GB 的数据——这在硬盘时代是非常痛苦的。数百万行是 26 年前我在第一个商业级数据库项目中的一个笑话。今天,数十亿只是零钱。
这是一个 table 结构(类似于我看到的实现的结构),它将摘要统计信息分为周、日期(或天)和小时 tables 与主要连接外键关系的键。它不是将一天中的不同时间存储为列(在 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);
变量
变量和 insert/update 语句(根据最适合 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