6

我长期使用面向行的数据库设计,除了数据仓库项目和大数据样本外,我没有为 OLTP 应用程序使用面向列的数据库设计。

我的面向行的表看起来像

ID, Make, Model, Month, Miles, Cost
1   BMW   Z3     12     12000  100

我们团队中有些人提倡面向列的数据库设计。他们建议所有列名都应该是属性表中的属性名。然后另一个表 Quote 将有两列 PropertyName 和 PropertyValue。

在 .net 代码中,我们读取每个键并比较并转换为强类型对象。代码真的越来越乱了。

if (qwi.DomainCode == typeof(CoreBO.Base.iQQConstants.MBPCollateralInfo).Name)
     {
        if (qwi.RefCode == iQQConstants.MBPCollateralInfo.ENGINETYPE)
        {
           Aspiration = qwi.Value;
        }
        else if (qwi.RefCode == iQQConstants.MBPCollateralInfo.FUELTYPE)
        {
           FuelType = qwi.Value;
        }
        else if (qwi.RefCode == iQQConstants.MBPCollateralInfo.MAKE)
        {
           Make = qwi.Value;
        }
        else if (qwi.RefCode == iQQConstants.MBPCollateralInfo.MILEAGE)
        {
           int reading = 0;
           bool success = int.TryParse(qwi.Value, out reading);
           if (success)
           {
              OdometerReading = reading;
           }
}
}

这种面向列的设计的论点是我们不必更改表模式和存储过程(我们仍然使用存储过程而不是实体框架)。

似乎我们正面临真正的问题。面向列的设计在行业中是否被广泛接受。

4

5 回答 5

11

我对你的术语有疑问。您正在描述 EAV 结构(代表实体-属性-值)。

旁白:“面向列”的数据库通常是指将每列与其他列分开存储的数据库(当我了解数据库时,这被称为“垂直分区”,但我认为这并不流行)。示例包括 Paracel 和 Vertica。

实体属性值数据库将实体的每个属性存储为单独的行。

您的特定结构遇到的第一个问题是打字。有些属性是字符串,有些是数字。这成为 EAV 世界中的管理噩梦。要么将所有内容存储为字符串(失去输入检查值并保证算术字的能力),要么将不同类型的多个列包含在类型列中(使查询更加复杂)。

同样,约束和外键引用更难实现。此外,由于您在每一行上重复实体 id 和属性 id,因此数据通常会占用更多空间。 NULL值通常非常节省空间。

在 OLTP 方面,您还有另一个问题。当你想插入一个实体时,你通常也想插入一堆属性。一个插入现在变成了许多插入,您需要开始将它们包装在事务中,从而影响性能。

鉴于所有这些缺点,您可能认为永远不要使用 EAV 模型。有他们的地方。当属性随时间变化时,它们特别有用。比如说,如果您有一个应用程序,用户可以在其中使用标签输入他们自己的信息。在这种情况下,混合方法是最佳解决方案。使用具有许多列的常规关系表来获取公共信息。使用 EAV 表获取每个实体的可选信息。

于 2013-09-16T15:39:54.057 回答
5

资料来源:维基

  1. 当需要对多行计算聚合时,面向列的组织效率更高,但仅针对所有数据列中明显较小的子集,因为读取较小的数据子集可能比读取所有数据更快。
  2. 当一次为所有行提供列的新值时,面向列的组织效率更高,因为可以有效地写入列数据并替换旧列数据,而无需触及行的任何其他列。
  3. 当同时需要单行的许多列时,面向行的组织效率更高,并且当行大小相对较小时,可以通过一次磁盘查找来检索整行。
  4. 如果同时提供所有列数据,则面向行的组织在写入新行时效率更高,因为可以使用单个磁盘查找来写入整行。

在实践中,面向行的存储布局非常适合类似 OLTP 的工作负载,这些工作负载更多地承载着交互式事务。面向列的存储布局非常适合类似 OLAP 的工作负载(例如,数据仓库),这些工作负载通常涉及对所有数据(可能是 TB)进行少量高度复杂的查询。

于 2013-09-16T15:28:35.207 回答
3

除了 Gordon Linoff 提到的问题之外,EAV 数据模型也非常难以查询 - 查找制造商为 BMW 并且月份在 12 到 24 之间且成本 < 10000 的所有汽车变成了一大堆讨厌的 SQL,尤其是如果你'正在对数字进行字符串比较...

于 2013-09-16T16:20:31.773 回答
0

通常面向行和面向列是低级别(磁盘)的存储机制。每个存储的优劣取决于您的要求。在某些情况下,面向列的存储效果会更好,而在某些情况下,面向行的存储效果会更好。

在 Hbas 数据库中,他们使用列族的概念,即列组。

面向行的区别在于,由行组成的逻辑表每个行块存储一行,而面向列的每个列块存储一列。

当我们发起分析查询(如工资总和、工资平均值)时,面向行的结果会导致性能不佳,但当我们需要访问行的单个详细信息或插入新记录时工作正常。而面向列在分析查询上工作得很好,但会导致插入单个记录或访问行的所有细节的性能很差。

您可以访问此链接,该链接通过示例描述了不同场景的优缺点以及它们的总结差异。

点击这里: http: //geekrandomstuff.blogspot.tw/2014/04/row-orientation-database-vs-column.html

于 2014-04-24T11:12:25.727 回答
0

根据我的经验,EAV 非常适合存储应用程序设置,即。相对静态的数据,无需进一步连接和转换数据,仅此而已。

于 2015-05-15T08:41:06.223 回答