面向列的数据库与面向行的数据库

时间:2013-09-16 15:24:54

标签: sql database database-design architecture

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

我的面向行的表看起来像

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

我们团队中的一些人主张面向列的数据库设计。 他们建议所有列名都应该是Property表中的属性名。 然后另一个表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;
           }
}
}

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

好像我们正在走向真正的问题。以列为导向的设计在业界得到广泛认可。

5 个答案:

答案 0 :(得分:11)

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

除此之外:“面向列的”数据库通常指的是一个数据库,它将每个列与其他列分开存储(当我了解数据库时,这被称为“垂直分区”,但我认为这并不存在)。例子包括Paracel和Vertica。

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

您对特定结构的第一个问题是输入。一些属性是字符串,一些是数字。这成为EAV世界的管理噩梦。您可以将所有内容存储为字符串(无法输入检查值并保证算术字),或者为类型列包含不同类型的多个列(使查询更加复杂)。

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

在OLTP端,您还有另一个问题。如果要插入实体,通常还需要插入一组属性。现在,一个插入已经转换为许多插入,并且您将要在事务中开始包装它们,从而影响性能。

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

答案 1 :(得分:5)

资料来源:WIKI

  1. 当需要在许多行上计算聚合时,面向列的组织更有效,但仅针对所有数据列的一个明显更小的子集,因为读取较小的数据子集可能比读取所有数据更快。
  2. 当一次为所有行提供列的新值时,面向列的组织会更有效率,因为可以有效地写入列数据并替换旧列数据而不触及行的任何其他列。
  3. 当同时需要单行的多列时,以及当行大小相对较小时,面向行的组织会更高效,因为可以使用单个磁盘搜索来检索整个行。
  4. 如果所有列数据同时提供,则在编写新行时,面向行的组织会更有效率,因为整个行可以使用单个磁盘搜索进行写入。
  5. 实际上,面向行的存储布局非常适合类似OLTP的工作负载,这些工作负载的交互式事务负载更重。面向列的存储布局非常适合类似OLAP的工作负载(例如,数据仓库),这些工作负载通常涉及对所有数据(可能是太字节)的较少数量的高度复杂查询。

答案 2 :(得分:3)

除了Gordon Linoff提到的问题之外,EAV数据模型也非常难以查询 - 找到制造商是宝马的所有汽车以及12到24之间的月份和成本< 10000变成了一个讨厌的SQL的巨大混乱,特别是如果你正在对数字进行字符串比较......

答案 3 :(得分:0)

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

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

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

当我们触发分析(如工资总额,工资平均值)的查询时,行导向导致性能不佳,但是当我们需要访问行的隐含细节或插入新记录时工作正常。而面向列的分析查询在分析查询中工作正常,但导致单个记录的插入或访问行的所有细节的性能较差。

您可以访问此链接,其中描述了不同场景的优缺点以及示例及其摘要差异。

点击此处:http://geekrandomstuff.blogspot.tw/2014/04/row-oriented-database-vs-column.html

答案 4 :(得分:0)

根据我的经验,EAV非常适合存储应用程序设置,即。相对静态的数据,不再需要加入和转换数据,仅此而已。