回答

收藏

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

技术问答 技术问答 296 人阅读 | 0 人回复 | 2023-09-13

我长期使用面向行的数据库设计,除了数据仓库项目和大数据样本外,我没有为OLTP应用程序使用面向列的数据库设计。
2 i% v1 a! r& P& W" z4 `- o, Z我的面向行的表看起来像
  D9 T( e! `5 Z5 u; n; L6 EID, Make, Model, Month, Miles, Cost, ~9 M# A: x  W9 j
1   BMW   Z3     12     12000  100
$ x& T9 ~2 @$ ~0 Z: ~- F我们团队中的某些人提倡面向列的数据库设计。他们建议所有列名称都应该是“属性”表中的属性名称。然后,另一个表Quote将具有两列PropertyName和PropertyValue。  }+ I- @: x4 b2 f) x! C5 ?* B/ S
在.net代码中,我们读取每个键并进行比较并将其转换为强类型对象。代码真的变得一团糟。
) M" T& a' Z, m6 N  W- mif (qwi.DomainCode == typeof(CoreBO.Base.iQQConstants.MBPCollateralInfo).Name)4 |; K6 _$ l2 [: N6 Z( X$ R3 X4 H
     {& {$ R& t1 [  S: F5 O  [
        if (qwi.RefCode == iQQConstants.MBPCollateralInfo.ENGINETYPE): V; r) r, S2 c6 k4 U; N
        {; ?' }+ D6 K; _( Y" }
           Aspiration = qwi.Value;$ r# m: {6 v+ k5 C9 Q$ I
        }
& c, y6 E2 F2 [# M: M3 V; M        else if (qwi.RefCode == iQQConstants.MBPCollateralInfo.FUELTYPE)
4 W# q8 k! F  p# Y( P        {
# @" t  [9 j* C; i: l( {           FuelType = qwi.Value;  K! J$ v. k3 s& b( F
        }' B2 W$ i# |4 [1 l( b' I& k2 p9 R
        else if (qwi.RefCode == iQQConstants.MBPCollateralInfo.MAKE)
" ~: T3 e3 h0 s7 w6 @9 p( s8 n3 E        {
  H4 E! e; J, q* J2 S" a           Make = qwi.Value;; l4 D' c2 T0 O" W% Z' j
        }
! ^" m- g, Q9 {' Q" e( Q1 q        else if (qwi.RefCode == iQQConstants.MBPCollateralInfo.MILEAGE)
6 x- q" x& @# q7 g: l        {
& ~& O* i' k4 V. s$ z% S           int reading = 0;2 ]" P3 ~9 B5 @& z0 N
           bool success = int.TryParse(qwi.Value, out reading);
1 v* c* B2 ^  P' m3 [2 s9 c           if (success)
6 A$ u3 H9 v+ A# u           {
7 C# s1 b9 ~6 \" R; ?. l5 Q) o1 {              OdometerReading = reading;
' ~3 i) ~/ R" p7 \6 l7 H7 {           }
  F4 q/ s4 x6 T; t: g}
8 i# H$ Q5 {1 Y# a}% p: F3 u7 M* `) x- W
这种面向列的设计的争论在于,我们不必更改表架构和存储的proc(我们仍在使用存储的proc而不是Entity Framework)。
8 |+ Y. W1 A' s1 ?; }7 o3 _似乎我们正在走向真正的问题。面向列的设计在业界已广为接受。
9 L( f' x2 J' v; d$ o1 y                & w) j2 \) l: @0 I1 E6 s
解决方案:4 W4 U7 D& v2 \0 l& {/ l5 D+ }- C
                0 q  H2 o' A7 p. ~7 w
2 F2 g% b) T- U) E! x
( o8 F5 t( E3 B  s/ o: w
                我在用您的术语时遇到麻烦。您正在描述一个EAV结构(代表Entity-Attribute-Value)。
5 [9 [0 A/ U9 n4 X9 Y另外:“面向列”数据库通常是指将每一列与其他列分开存储的数据库(当我了解数据库时,这被称为“垂直分区”,但我认为这并不流行)。示例包括Paracel和Vertica。
9 t- }+ d' {# F$ X. `+ ?实体属性值数据库将实体的每个属性存储为单独的行。3 |, o3 u- p2 w; s3 I$ r
特定结构的第一个问题是键入。一些属性是字符串,一些属性是数字。这成为EAV世界中的管理梦night。您要么将所有内容存储为字符串(失去键入检查值的能力并保证算术单词),要么将类型不同的多个列包含在类型列中(使查询复杂得多)。- _, n2 k) S8 \/ N
同样,约束和外键引用很难实现。另外,由于您要在每一行上重复实体ID和属性ID,因此数据通常会占用更多空间。 NULL值通常非常节省空间。
' q5 l7 S0 L& h$ R$ I4 C在OLTP方面,您还有另一个问题。当您要插入实体时,通常还希望插入一堆属性。现在,一个插入已变成许多插入,您将需要开始将它们包装在事务中,从而影响性能。3 a( z9 C% S( j8 o9 X, G. L5 r
考虑到所有这些缺点,您可能会认为 永远不要$ i7 W  X( d9 d, [7 I
使用EAV模型。有一个适合他们的地方。当属性随时间变化时,它们特别有用。说,如果您有一个应用程序,用户可以在其中添加带有标签的自己的信息。在这种情况下,混合方法是最佳解决方案。使用包含许多列的常规关系表来获取公共信息。将EAV表用于每个实体的可选信息。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则