Database-Design

星型模式數據倉庫中動態欄位的 EAV 替代方案

  • October 23, 2014

我需要在大數據倉庫中支持動態欄位和值來儲存 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 的架構

  1. requests

(id, timestamp, uri)

例如(1, 149382220, '/') 2. 表params

(request_id, key, value)

例如(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

有什麼建議?

更新:我們在 AWS RedShift 上執行倉庫

我能想到三種解決方案——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 的能力,這很好地滿足了我的需求。

引用自:https://dba.stackexchange.com/questions/64689