Database design 我应该减少表并使用复杂查询来获取数据,还是应该增加表以简化查询?

Database design 我应该减少表并使用复杂查询来获取数据,还是应该增加表以简化查询?,database-design,database-table,Database Design,Database Table,让我们以一个senario为例,其中用户正在跟踪特定城市的流量。流量每两小时更新一次,我们必须保留以前的数据来绘制图表。所以我有一个流量统计表如下所示- traffic_stats(id,city_id,user_id,traffic,created_at) (给定的流量是一个数字) 有一个统计刷新守护程序,它接受唯一的城市ids,获取这些城市的当前交通统计数据,并将新条目添加到此表本身。守护进程使用此查询获取city\u id- SELECT * FROM traffic_stats GRO

让我们以一个senario为例,其中用户正在跟踪特定城市的
流量
。流量每两小时更新一次,我们必须保留以前的数据来绘制图表。所以我有一个
流量统计表
如下所示-

traffic_stats(id,city_id,user_id,traffic,created_at)
(给定的流量是一个数字)

有一个统计刷新守护程序,它接受唯一的
城市id
s,获取这些城市的当前交通统计数据,并将新条目添加到此表本身。守护进程使用此查询获取
city\u id
-

SELECT * FROM traffic_stats GROUP BY city_id
并为同一表格中的每个
城市id
添加新条目。每个新条目的
user\u id
属性为0,因为哪个用户订阅了城市并不重要。如果
city\u id
在表中,则刷新其交通统计数据

在前端,运行以下查询为用户获取数据-

SELECT * FROM 
(SELECT * FROM traffic_stats WHERE user_id = #{session[:user_id]} ORDER BY created_at DESC)
as traffic_for_user_in_descending_order 
GROUP BY city_id
这将为城市id提供一个最新的条目

这应该可以正常工作,但如果100个用户正在跟踪200个独特的城市,那么每两小时
交通统计表中就会有200个新条目。那是
每天有2400个条目,该表将继续增长


现在,我可以有一个表,其中包含用户正在跟踪的城市的数据,另一个表由刷新守护进程添加条目。但是我不确定这种方法是否有任何性能优势。

最好创建一个单独的城市表,这样您就可以从中查询不同的城市ID,而不是在第一个select语句中扫描整个表。这也会使读取数据库变得更容易。如果您不想这样做,我建议使用
从交通统计中选择不同的城市id
。这样,您将检索到更少的信息

在这种情况下,拥有一个表似乎是合理的,因为您使用信息的应用程序很简单。至于历史数据,最好创建一个单独的表来存储聚合信息。您可以修剪主表,选择并存储特定时间长度(天、周、月等)的平均值,然后根据用户id的信息进行更多筛选。这将减少数据库磁盘使用和查询时间


就我个人而言,我喜欢尽可能地把事情弄清楚。它确实使查询更加复杂,但在我看来,它使使用和读取数据库中的信息更加容易。

最好创建一个单独的城市表,这样您就可以从中查询不同的城市ID,而不是在第一个select语句中扫描整个表。这也会使读取数据库变得更容易。如果您不想这样做,我建议使用
从交通统计中选择不同的城市id
。这样,您将检索到更少的信息

在这种情况下,拥有一个表似乎是合理的,因为您使用信息的应用程序很简单。至于历史数据,最好创建一个单独的表来存储聚合信息。您可以修剪主表,选择并存储特定时间长度(天、周、月等)的平均值,然后根据用户id的信息进行更多筛选。这将减少数据库磁盘使用和查询时间


就我个人而言,我喜欢尽可能地把事情弄清楚。它确实可以进行更复杂的查询,但在我看来,它使使用和读取数据库中的信息更加容易。

您应该在一个单独的表中,如
user\u city
中,将
城市id
用户id
分开。然后,类似于
selectdistinct city\u id from user\u city
的查询将为守护进程提供跟踪城市的列表。如果正确设置了索引、FK等,则表的增长大小应该无关紧要

如果
user\u id
traffic\u stats
中始终为0,那么
WHERE user\u id={session[:user\u id]}
在查询工作中如何工作


使用所有可能索引的复杂查询是可以的。如果您每天/每周都要做统计摘要,那么您还应该按照rallsi23的建议创建一个表来存储聚合数据。这样,您就不会读取统计表的每一行来生成输出/报告给用户。

您应该在一个单独的表中,如
user\u city
中,将
city\u id
user\u id
分开。然后,类似于
selectdistinct city\u id from user\u city
的查询将为守护进程提供跟踪城市的列表。如果正确设置了索引、FK等,则表的增长大小应该无关紧要

如果
user\u id
traffic\u stats
中始终为0,那么
WHERE user\u id={session[:user\u id]}
在查询工作中如何工作


使用所有可能索引的复杂查询是可以的。如果您每天/每周都要做统计摘要,那么您还应该按照rallsi23的建议创建一个表来存储聚合数据。这样,您就不用读取统计表的每一行来向用户生成输出/报告了。

谢谢。我意识到打破东西实际上是最好的方法,尽管它增加了几张桌子。为什么建议使用DISTINCT over GROUP BY?
DISTINCT
忽略所有不必要的信息,这意味着您只检索所需的列,检索该列要比让数据库对它找到的所有结果进行排序更快。我需要更多的列来渲染视图。在这种情况下,我认为不可能同时使用DISTINCT和get“id”列。谢谢。我意识到打破东西实际上是最好的方法,尽管它增加了几张桌子。你为什么要暗示