我是否应该使用更少的表并使用复杂的查询来获取数据或使用更多的表来简化查询?

时间:2012-10-05 01:55:26

标签: database-design database-table

让我们来看一个用户正在跟踪traffic某个cities的情况。流量每两小时更新一次,我们要将之前的数据保存到绘图中。所以我有一个traffic_stats表,看起来像这样 -

traffic_stats(id,city_id,user_id,traffic,created_at)

(给定流量是一个数字)

有一个统计数据刷新守护程序,它采用唯一 city_id,获取这些城市的当前流量统计信息,并为此表本身添加新条目。守护程序使用此查询来获取city_id -

SELECT * FROM traffic_stats GROUP BY city_id

并在同一个表中为每个city_id添加新条目。每个新条目的user_id属性为0,因为哪个用户订阅了该城市无关紧要。如果city_id在表中,则刷新traffic_stats。

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

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

这为city_id提供了单个最新 条目。

这应该可以正常工作,除非100个用户正在跟踪200个独特城市,每两小时traffic stats表中将有200个新条目。那是 每天2400个条目,表格将继续增长。

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

2 个答案:

答案 0 :(得分:2)

创建单独的 City 表可能更好,这样您就可以从中查询不同的城市ID,而不是在第一个select语句中扫描整个表。它还可以使数据库读取更容易一些。如果您不想这样做,我建议您使用SELECT DISTINCT city_id FROM traffic_stats。这样您就可以获取更少的信息。

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

我个人喜欢尽可能地解决问题。它确实可以用于更复杂的查询,但是在我看来,它使得从数据库中使用和读取信息变得更加容易。

答案 1 :(得分:2)

您应该在city_id这样的单独表格中展开user_iduser_city。然后像SELECT DISTINCT city_id from user_city之类的查询将为您提供守护程序的跟踪城市列表。如果您正确设置索引,FK等,则表的大小不应该重要。

如果user_id中的traffic_stats始终为0,那么查询中WHERE user_id = #{session[:user_id]}的工作原理是什么?

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