【问题标题】:SQL database restylingSQL 数据库重新设计
【发布时间】:2013-11-20 14:08:36
【问题描述】:

最近几天,我打电话来替代我公司的一名前 dba 总结一下,该公司负责气象数据的存储。 也就是说,自 1996 年以来,已经以不同的方式(txt、xls、然后访问等)测量和存储了许多变量 去年,所有这些数据都必须存储在 sql db (sql server 2008 r2) 中,但我发现了一个奇怪且不简单的情况 实际上,大约有 30 个表,每个表都有不同的列数。 每列都是一个变量,在我们的数据库中存在 300 多个变量 表的结构类似: id, siteid, date_of_meas, var1, var2,...,varN(复制 30 次)

首先,变量没有按逻辑分组(压力与温度等),但最糟糕的是,每次创建新变量时(取决于实际因素,这里没有什么有趣的讨论),前 dba 采取行动这边走: 1. 向现有表添加新列(...如果表已经有 50 列...?) 2.写入数据 正如你所知道的那样,在我看来,这种方式真的很疯狂

我会从头开始重新设计数据结构。 情况是这样的:有一个包含所有现有变量的表(添加新变量没问题) 我可以使用变量的 id 号,创建新表(对它们进行逻辑分组......但总会有很多表)并使用这些外键插入数据。 类似于以下内容:

CREATE TABLE [dbo].[MyMeteo](
[id_meteo] [int] IDENTITY(1,1) NOT NULL,
[varid] [int] NOT NULL,
[siteid] [int] NOT NULL,
[date] [smalldatetime] NOT NULL,
[value] [float] NULL,

....

另一个问题是数据量非常大...由于每 30 分钟测量一次数据,因此在 1 年内有 17520 或 17568 次测量。 将其乘以 15 年,300 个变量和 200 个站点……我正在考虑 sql 数据库是否仍然是正确的选择。 非常感谢 迭戈

【问题讨论】:

  • 不用担心数据量。只要您的硬件符合要求并且您购买了正确版本的 SQL Server,这方面就可以了。
  • “未按逻辑分组(压力与温度等)”——但是,PV = NkT。对我来说,这实际上似乎是合乎逻辑的。
  • 查看表分区以获得更快的查询访问,但数据量是 SQL Server 无法处理的。

标签: sql sql-server-2008 database-design


【解决方案1】:

类似于以下内容:

CREATE TABLE [dbo].[MyMeteo](
[id_meteo] [int] IDENTITY(1,1) NOT NULL,
[varid] [int] NOT NULL,
[siteid] [int] NOT NULL,
[date] [smalldatetime] NOT NULL,
[value] [float] NULL,

... 是entity-attribute-value 模式的一个细微变化。这是一个模式。

您以前的 DBA 可能做对了:每次测量一行,每个变量作为一列。如果这意味着 50 列或更多列,这无关紧要。

如果需要,可以在单独的表中拆分逻辑组。实际上,不要:您将获得更复杂的查询计划和更慢的查询(有时会慢得多,当按存储在一个表中的条件排序而按存储在另一个表中的条件进行过滤时),即对您的麻烦几乎为零。

简而言之,最终对您而言最重要的是挖掘数据的简单程度。跨表拆分数据会使情况变得更糟。使用像您正在研究的那种伪 EAV 商店会让事情变得更糟很多

关于最后一点,SQL 是正确的选择:160 亿行虽然令人印象深刻,但对于现代数据库来说仅比小数字高出几个档次。

【讨论】:

    【解决方案2】:

    如果数据可以静态关系映射,则 EAV 是一种反模式。 我不太确定这里的情况。

    我们似乎在谈论一组变量:不仅添加了新变量,而且我猜随着时间的推移,有些变量会不再使用。

    拥有数百列意味着每次我想挖掘数据时都要进行单独的静态查询,而在这种情况下,EAV 让我可以非常简单地收集变量X 在给定时间段内的所有测量值,简单的可重用查询。对变量 ID 进行索引也可能会加快对数据库的操作,因为具有 50 列大部分为空的数据库将花费更长的时间来搜索(除非您索引所有 50 列,即使它们可能 98% 的时间都是空的)。

    在这种情况下 EAV 是否​​是最优的尚有争议,因为我认为我们没有所有信息来决定这一点,但我认为简单地说明 EAV 始终是反模式并没有建设性。

    【讨论】:

    • 但是,现实生活中的查询很少是 varX 的那些简单选择,不是吗? :-) 在我自己的软件 ghetto 中,它们更像是:在另一组中显示一组符合某些标准的变量,然后聚合数据以计算统计数据,可能通过对另一组进行分组,过滤混乱并排序由更多的点点滴滴。使用 OP 的 EAV 想法,这是一个科学怪人的混乱连接,几乎不可能有效地计划(更不用说执行)了。没有,这是一个简单的选择/聚合计划;一些战略性放置的索引在这里和那里,结果很快就会弹出。
    • 当然,但在谈到最佳方法时,现实生活也很少是非黑即白的。仍然在您更复杂的查询中,我宁愿不必在每个选择或连接中处理 var123 和 var543 之类的列名。 EAV 在很多情况下确实很糟糕,我完全同意,但这并不意味着它没有应用程序。而且我觉得这可能不是一个糟糕的候选人:)
    • 我不同意。我见过 EAV 唯一有用的地方是存储元数据。这里的操作词是“元”:在应用程序的整个生命周期中,您很少会在查询中的任何地方找到这些字段。根据我自己的经验,任何缺少的东西都值得一个(正确输入的)专栏。好的 EAV 候选包括:用户的 display_name_pref,网页的 template_name,即只对应用程序感兴趣的东西。如果它可以放在 JSON blob 中,它可以放在 EAV 存储中……坏的包括可能出现在聚合函数或 where 子句中的任何内容。