使用 Eav 模型构建可无限扩展的数据存储能力 |
您所在的位置:网站首页 › CDM代码可上32G › 使用 Eav 模型构建可无限扩展的数据存储能力 |
举个例子
假设要做一个电商的商品管理,我们先卖一些衣服,需要管理衣服的尺码、颜色、款式等信息,有一天需要卖电脑了,电脑需要 主板、CPU、显卡、内存、硬盘、散热 等信息,过几天又需要卖手机了,手机有 颜色、版本、存储容量、套餐类型等等信息,数据库如何设计。 方案一:新增字段每次新增商品,需要支持不同的信息的话就不停的加字段。 IDName尺码颜色款式主板CPU显卡内存存储散热版本套餐类型1T恤M白色喜羊羊NULLNULLNULLNULLNULLNULLNULLNULL2外星人电脑NULLNULLNULLAi99RTX809032G2T水冷NULL键鼠套装3香蕉手机NULL五彩斑斓黑NULLNULL晓龙999NULL12G512G风扇Pro Plus MAX碎屏险套餐这样会造成以下问题: 实现成本高,每次添加商品都需要进行前后端开发、调试,浪费时间和人力。需要动态变更表结构,在生产环境中安全性太低。浪费资源,数据库的字段可能会越来越多,而很多字段大部分商品都是不需要的,需要设置为NULL,导致内存大量浪费。扩展能力一般,有上限。 方案二:预留字段给对应的表定义几个预留字段,然后这些预留字段在不同的商品可以重复使用。这样的话可以解决一部分的开发问题,大部分情况不需要开发,直接复用现有字段就可以。 IDNameExt1Ext2Ext3Ext4Ext5Ext6Ext71T恤M白色喜羊羊NULLNULLNULLNULL2外星人电脑Ai99RTX809032G2T水冷键鼠套装3香蕉手机五彩斑斓黑晓龙99912G512G风扇Pro Plus MAX碎屏险套餐但是这样也有很多问题: 字段一样,但是含义不一样,需要前端做大量适配。字段的类型可能不一样,预留字段还得考虑不同的类型。预留字段太少了作用有限,太多了和新增字段一样会有存储和性能问题。扩展字段是公用的,不能根据字段名顾名思义,得在启用时维护对应关系,使用时查找对应关系。扩展字段的数量无法精确定义。 方案三:JSON_OBJECT这种情况下有一种简单的解决方案,就是设计一个 extra 字段,类型为 JSON,然后把 尺码、颜色、款色、主板、CPU、显卡、内存等等都放到 JSON 里。 IDNameExt11T恤{ "尺码": "M", "颜色": "白色", "款式": "喜羊羊" }2外星人电脑{ "主板": "A", "CPU": "i9 11900", "显卡": "RTX8090", "内存": "32G", "存储": "2T", "散热": "水冷", "套餐类型": "键鼠套装" }3香蕉手机{ "颜色": "五彩斑斓黑", "CPU": "骁龙999", "版本": "Pro Plus MAX", "内存": "12G", "存储": "512G", "散热": "风扇", "套餐类型": "碎屏险套餐" }但是 JSON 有以下几个问题: JSON 数据仅仅只能用于展示,如果用于条件查询、数据更新其效率是很低的。查询时需要遍历表解析 JSON。虽然 MySQL 支持了 JSON 类型,但 MySQL 作为关系型数据库,对标准化的 column-per-value 支持更好,包括数据类型限制、长度限制,唯一索引限制,查询索引优化,外键关联,关联查询支持,运算支持等,这些都是 JSON 中 Key 无法达到的。将常用的查询字段从 JSON 数据中剥离出来形成单独的字段,虽然可以改善查询问题,但需要有先见之明,如果后期进行剥离就会涉及代码修改和数据迁移,遇到多版本的话,还可能出现数据冗余的问题,处理不好还会出现数据不一致问题,并不仅仅这么简单,一定慎用。大 JSON 的解析性能较差。每条数据都需要同时保存 Key 和 Value,对于中文数据,纯 JSON 太占空间了。 基于以上几个原因,在一些复杂的情况下,不建议使用 JSON 存数据。 以上三种都不是理想的解决方案,后续经过不断的经验积累,提出来了 EAV 模型,可以在一定程度上解决以上问题。 什么是 EAV 模型Entity-Attribute-Value (wiki)是一种数据模型,用于以节省空间的方式对实体进行编码。 Entity:实体,代表一个业务对象,比如上面的例子里的商品。Attribute:对象的属性,属性并不是作为实体单独的一列来进行存放,而是存储在一组单独的数据库表中。Value:指特定属性所关联的值。 几个概念 稀疏属性(Sparseness of Attributes)在数学和计算机科学中,如果一个对象仅包含大量潜在属性中的几个属性,称之为“稀疏矩阵”。在讨论EAV 时,采用“稀疏”来描述大多数无值的属性。如上文中的主板、CPU、显卡等属性。 行模型(Row Modeling)基于行模型的表,其描述实体的数据记录为多行,每组新的数据在数据库中存为额外的行而非额外的列。行模型是数据库设计的标准数据建模技术,它仅适用于满足如下两个条件的情况: 特定实体的数据是稀疏的。数据是经常变动的。行模型是不适用于稀疏且数据非波动的情形,此时,应采用传统的列模型。 EAV 与行模型EAV 模型是行模型的泛化。行模型的表的数据是均匀的,这意味着整个数据库所有类型的数据存储在一张表中;此外,行模型表中值列的数据类型是预先确定的。而在 EAV表中,特定行其值的数据类型由对应的属性确定。 选择数据模型的最佳方法是很难的,但作为一个准则,如满足如下条件时使用EAV模型而非行模型: 数据记录中的单个属性的数据类型不同;采用行模型时一张表中很难存储不同类型的值。需要表示多种类型的数据,其数量可能出现波动。与此同时,即使不稀疏的属性,然每类数据都非常少。这种情况下,传统的数据模型将使成百的表却只有几行数据。在一定的环境中,其属性必须动态创建,某些类在原型随后的周期中常常会被省略。某些实体有混合型的属性,这意味着一些属性是非稀疏的,而其他属性则是高度稀疏的。在这种情况下,非稀疏属性存储在传统表中,而稀疏的属性存储在EAV或行建模的格式。 表结构设计 方案一:行模型先来一个简单的方案,使用行建模的方式。商品作为实体存入 Goods 表中,其余的属性和值存入商品属性表 Attribute 中。 商品表(Goods) GoodsIDName1T恤2外星人电脑3香蕉手机商品属性表(Attribute) GoodsIDAttributeValue1尺码M1颜色白色1款式喜羊羊2主板A2CPUi992显卡RTX80902内存32G2存储2T2散热水冷2套餐类型键鼠套装3颜色五彩斑斓黑3CPU骁龙9993内存12G3存储512G3散热风扇3版本Pro Plus MAX3套餐类型碎屏险套餐上面这个方案是行模型的方案,通过这种方式我们可以无限的扩展商品的属性。这种方案比较适用于每个实体的属性都不固定的情况。 但是这种方案有以下几个问题: 每条数据都需要同时保存 Key 和 Value,对于中文数据,Key 有限,行无限的情况下,会浪费大量空间,性能也比较差。Value 没有类型限制,都是 VARCHAR 的,对数据库不友好,会导致内存浪费,而且存取都需要进行数据格式转换。对存储为字符串的值创建的索引不允许针对数值型和日期型的搜索范围优化,这是采用混合数据类型的键-值对描述数据的公共问题。 方案二:简单 EAV针对方案一的第一个问题进行优化。 商品表保持不变。商品属性表拆分为属性表和值表。 属性表(Attribute) AttributeIDName1颜色2尺码3款式4主板5CPU6显卡7内存8存储9散热10版本11套餐类型值表(Value) GoodsIDAttributeIDValue12M11白色13喜羊羊24A25i9926RTX80902732G282T29水冷211键鼠套装31五彩斑斓黑35骁龙9993712G38512G39风扇310Pro Plus MAX311碎屏险套餐这样属性都保存在属性表里,每个属性值都保存在值表里,同时与商品表和属性表做关联,这样就可以大大节省内存。 方案三:优化 EAV为了解决方案一的第二个问题,则需要对值表基于数据类型进行分割,每个不同的数据类型拆为一个单独的表,同时通过 属性表(Attribute) 添加 类型决定去哪里存取数据。 属性表(Attribute) AttributeIDNameType1颜色VARCHAR2尺码INT3款式INT4主板VARCHAR5CPUINT6显卡INT7内存INT8存储INT9散热VARCHAR10版本TEXT11套餐类型VARCHAR值表 eav_int GoodsIDAttributeIDValue(INT)122(M)131(喜羊羊)2599(i99)268090(RTX8090)2732(32G)282048(2T)35999(骁龙999)3712(12G)38512(512G)eav_varchar GoodsIDAttributeIDValue(VARCHAR)11白色24A31五彩斑斓黑39风扇311碎屏险套餐211键鼠套装eav_text GoodsIDAttributeIDValue(TEXT)310Pro Plus MAX这种就是比较标准的 EAV 模型。解决了方案一的两个问题。 EAV 的优/缺点 优点EAV模型的主要优点是其灵活性。属性描述表不限制数量,这意味着每次新增属性不需要重新设计数据结构;扩展数据库时,属性的数量可以垂直增加,而无需改变数据结构。 EAV只处理非空属性,不需要为空值保留额外的存储空间。这使得EAV模型相当节省空间。 物理数据格式是非常干净,类似于JSON/XML,很容易将数据映射为JSON/XML格式。 EAV模型可以极好地迅速扩展应用,因为它可以防止(属性)不断变化的后果。可以简单地记录任何结构的新数据,而不需要修改任何数据结构。 缺点当考虑EAV时,确定数据是否稀疏和数据量非常重要,因为采用不恰当的数据集时,EAV设计的复杂性超过了其优势所在。相对静态或简单数据选用传统的表结构更为合适。 相较于传统的数据结构,EAV的一个主要缺点是它在检索大容量数据时效率较低。在EAV模型中,数据更加分散,所以查询一个完整实体的记录需要多个表JOIN查询。更重要的是,当EAV模型应用于大数据量时,对于同一组EAV建模的数据描述,需要短暂或永久地在进行矩阵转积处理(Pivoting)(行列转换)。该操作易于出错且是CPU密集型的任务。 EAV模型的另一个局限性,需要制定额外的逻辑来完成传统数据结构下自动进行的事务。但是,利用现有的EAV工具可以降低此类工作的成本。 最后,理解EAV模型确实需要时间。它有一个明确的学习曲线,使的初级开发人员在真正理解其概念前,需要为此付出更多的精力。 结论应用 EAV 模型时,应考虑以下条件: 数据是稀疏的、异构的,一个实体的属性范围较广,且常引入新的属性。数据量非常大,有许多不同类型的数据,即使属性是非稀疏的。有许多混合属性,既具有稀疏也具有非稀疏属性。通常情况下,并不是所有的数据类满足EAV建模的要求。在实际在生产环境中,往往采用混合模式(mixed schema),包括传统的关系、EAV或合适的混合方法。 Magento 2数据库EAV模型结构Magento是一个用PHP程序语言编写的开源电子商务平台;其主要面向企业级应用,可处理各方面的需求,号称世界排名第一的电子商务系统。据统计,全球电子商务网站中使用magento搭建的占比高达31.4%!
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |