How*_*ard 13 data-warehouse database-design eav star-schema redshift
我需要在大数据仓库中支持动态字段和值来存储 API 请求日志,我的用户案例是我需要存储所有 API 请求查询字符串并能够在未来对它们执行查询(所以它不仅仅是存储,所以我不能为他们使用 blob)
例如 http://example.com/?action=test&foo=abc&bar=def...
我需要存储所有field => value映射,即(action => test), (foo => abc), (bar => def),由于该字段是如此动态,我找到的唯一解决方案是使用 Entity-Attribute-Value,但是,人们一直说这是一个非常糟糕的设计。
那么,考虑一下我上面的用例,什么是 EAV 的合适替代品?
我当前使用 KAV 的模式
表requests
(id, timestamp, uri)
例如(1, 149382220, '/')
表params
(request_id, key, value)
例如(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')
有什么建议?
更新:我们在 AWS RedShift 上运行仓库
Nat*_*lly 11
我可以想到三种解决方案 - EAV、XML 和稀疏列。后者是特定于供应商的,可能对您没有用处。
无论您选择哪种方法,您都可能希望考虑以原始格式、表格或平面文件存储原始请求数据。它将使尝试新的数据存储方式变得容易,如果您发现解析请求的方式有误,您可以重新加载数据,并提供使用批处理或“大数据”解析 API 请求的机会如果您发现您的数据仓库无法有效处理数据,请使用工具。
EAV注意事项
EAV/KVS,正如您在上面描述的那样,可能是最直接的实现。
不幸的是,它也将非常昂贵 - 要对常用键进行任何类型的有效查询,您需要在键列上建立索引,这可能会变得非常碎片化。查询特定键将非常昂贵。
您可以通过使用物化视图(许多供应商支持此功能)支持您的 EAV 存储来查询您关心的键或值,从而降低索引或索引扫描的成本。
XML
大多数企业数据库系统提供非常成熟的 XML 处理,包括验证、索引和复杂的查询。
将 API 请求作为 XML 加载到数据库中将为每个请求提供一个元组,这在逻辑上可能比在 EAV 表中具有未知行数更适合您。
这是否有效在很大程度上取决于您的 RDBMS 供应商和您的实现。
最大的缺点是,这可能是管理比原始请求的字符串操作更复杂的数据的唯一方法!
稀疏列/传统表
您可以将数据加载到传统的表结构中,每个键一列。
SQL Server 的稀疏列功能是 EAV 存储的绝佳替代品。带有稀疏列的表的行为与普通表非常相似,不同之处在于它最多可以有 30,000 列,并且稀疏列中的 NULL 值不占用表中的空间。
如果您经常查询几个特定的列和/或值,将它们与过滤索引(另一个 SQL Server 特定功能)相结合可以提供一种非常有效的 EAV 存储替代方案。
与其他供应商一起使用传统表可能是可行的——IBM 支持每个表超过 700 列,而 Oracle 支持大约 1000 列,并且诸如压缩或 Oracle 对尾随空值的处理等特性可能意味着您可以相当有效地存储 API 数据。
这种方法的明显缺点是,当您向 API 添加新密钥时,您需要相应地调整架构。
EAV 本身并不是一个糟糕的设计,它只是一种需要相当多的远见卓识的设计,并且可以随着数据量的增加而解决性能问题。可能是因为对于您的系统,它会运行良好。
当我设计一个存储查询字符串的系统时,我事先不知道我会对哪些字段感兴趣。我创建了一个表来以序列化的二进制格式存储查询字符串,并构建了一个允许我拆分查询的系统一旦我知道我感兴趣的部分,就将其串入其组成部分。从那里我创建了一组表格;查询字符串中通常包含的数据集各一个。
例如,我最终有一个表用于引用数据,一个用于目标请求数据,另一个用于用户相关项目,例如他们输入的搜索查询。
我发现能够将整个查询字符串作为 blob 存储在单个表中,同时提供将来拆分 blob 的能力,非常满足我的需求。