在 Redshift 中存储事件数据的最佳方式是什么?

Mik*_*ike 2 database data-warehouse bigdata amazon-web-services amazon-redshift

我是 Redshift 新手,正在寻找存储事件数据的最佳方法。数据由标识符、时间和有关当前状态的 JSON 元数据组成。

我正在考虑三种方法:

  1. 为每个事件类型创建一个表,并为每条数据创建一个列。
  2. 为事件创建单个表并将元数据存储为 JSON 字段。
  3. 为我可能想要存储的每个可能的数据块创建一个包含一列的表。

#1 的优点是我可以过滤所有数据字段,并且解决方案更加灵活。缺点是每次我想添加新事件时都必须创建一个新表。

#2 的优点是我可以将所有类型的事件放入一个表中。缺点是要过滤元数据中的任何数据,我需要在每一行上使用 JSON 函数。

#3 的优点是我可以轻松访问所有字段,而无需运行函数,并且不必为每种类型创建新表。缺点是无论谁使用数据都需要记住要忽略哪些列。

其中一种方法比其他方法更好还是我完全错过了一些东西?

Ale*_*Yes 5

这是一个经典的困境。经过思考一段时间后,在我的公司中,我们最终将事件的公共属性保留在单独的列中,并将唯一属性保留在 JSON 字段中。常见属性的示例:

  • 事件类型、时间戳(每个事件都有)
  • URL(后端事件和移动应用程序事件将缺少该 URL,但所有前端事件都会出现该 URL,并且值得在单独的列中包含)
  • 客户端属性:设备、浏览器、操作系统(后端将缺失,但会出现在移动应用程序事件和前端事件中)

独特属性的示例(其他事件中没有此类属性):

  • AB 测试事件中的测试名称和变体
  • 购买事件中的产品名称或 ID

通用属性和唯一属性之间的界限是您自己的判断,基于有多少事件共享此属性以及在分析查询中使用此属性来过滤或分组数据的频率。如果某些属性只是“拥有就好”并且不涉及常规分析用例(是的,我们都喜欢存储任何可跟踪的内容以防万一),那么维护单独列的负担就太过分了。

另外,如果您有一些在查询中广泛使用的独特属性,则有一种巧妙的优化方法。您可以将此属性放在 JSON 列的开头(是的,在 Python 中 JSON 没有排序,但在 Redshift 中它是一个字符串,因此如果需要,可以固定键的顺序)并仅在字段结束:

select * 
from event_table
where event_type='Start experiment'
and event_json like '{"test_name":"my_awesome_test"%'  -- instead of below
-- and json_extract_path_text(event_json,'test_name')='my_awesome_test'
Run Code Online (Sandbox Code Playgroud)

LIKE 使用这种方式比 JSON 查找快得多(快 2-3 倍),因为它不需要扫描每一行、解码 JSON、查找键并检查值,但它只检查字符串是否以子字符串开头(操作更便宜)。