2017-08-23 114 views
0

我想在數據庫(特別是PostgreSQL)中有效地存儲「set」,但我不確定如何有效地完成此操作。如何有效地在數據庫中存儲「set」(python類型)?

有一些流行想到幾個選項:

  • 存儲爲文本或二進制列的列表({'first item', 2, 3.14})。這具有在插入數據庫和拔出時需要解析的缺點。對於只有一組文本字符串,這似乎工作得很好,解析是最小的。對於更復雜的任何事情來說,解析變得困難。

  • 存儲爲二元列中的泡菜。這似乎應該是快速的,它是完整的(任何可挑選的作品),但不跨語言移植。

  • 存儲爲json(作爲二進制對象或文本流)。比純文本更大的問題,但定義更好的解析。

還有其他的選擇嗎?有沒有人有這些經驗?

回答

2

你想要做的是在你的表中的一行和集合的成員之間存儲一對多的關係。

您的解決方案都不允許通過SQL查詢該組的成員。你不能做像select * from mytable where 'first item' in myset這樣的東西。相反,您必須檢索文本/ blob並使用其他編程語言來解碼或解析它。這意味着,如果您想對組中的元素執行查詢,則每次都必須執行全表掃描。

我會非常不願意讓你在我的數據庫之一做這樣的事情。

我認爲你應該把你的設置分解成單獨的表格。我的意思是(因爲這顯然不如我想象的那麼明顯),每個集合元素有一行,索引在表中,您從引用的表的主鍵,或者如果您想強制執行沒有重複的代價一點額外的空間,您提到的表的主鍵 + 設置元素值

既然你設置的元素看起來是異構類型的,我認爲沒有什麼壞處將它們存儲爲字符串,只要你以某種方式規範化數字。

+0

據最新的統計,集合所有集合有600K元素。把它分成不同的列是不可行的,是嗎? –

+0

我看到600K行的表沒有問題。如果您擔心空間效率問題(從您的問題中不清楚),那麼我認爲您的JSON提案可能會佔用相同的空間。 – BoarGules

+0

關於元素的數量,你有600k * distinct *元素嗎?如果沒有,並且您擔心表空間(或者想要避免冗餘),則可以在連接表中存儲一個ID列表。我第二個@BoarGules參數,如果可能的話嘗試保持SQL數據在SQL中可管理(JSON是一個PITA,但以二進制形式存儲數據是一個definitice no-go)。 – Arminius

1

其中一種可能的方式是JSONB數組。它能夠存儲任何類型的元素,它可以通過索引來提高搜索速度:

create table t as 
    select '["first item", 2, 3.14]'::jsonb as x 
    from generate_series(1,100000); 
insert into t values('["second item", 3, 2.72]'); 
create index idx on t using gin(x); 

explain analyse select * from t where x @> '3'; 
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│             QUERY PLAN             │ 
╞═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Bitmap Heap Scan on t (cost=36.78..327.18 rows=100 width=47) (actual time=0.055..0.056 rows=1 loops=1)  │ 
│ Recheck Cond: (x @> '3'::jsonb)                    │ 
│ Heap Blocks: exact=1                      │ 
│ -> Bitmap Index Scan on idx (cost=0.00..36.75 rows=100 width=0) (actual time=0.028..0.028 rows=1 loops=1) │ 
│   Index Cond: (x @> '3'::jsonb)                   │ 
│ Planning time: 0.188 ms                      │ 
│ Execution time: 0.121 ms                      │ 
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 

explain analyse select * from t where x @> '[3, "second item"]'; 
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│             QUERY PLAN             │ 
╞═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Bitmap Heap Scan on t (cost=68.78..359.18 rows=100 width=47) (actual time=0.087..0.089 rows=1 loops=1)  │ 
│ Recheck Cond: (x @> '[3, "second item"]'::jsonb)               │ 
│ Heap Blocks: exact=1                      │ 
│ -> Bitmap Index Scan on idx (cost=0.00..68.75 rows=100 width=0) (actual time=0.048..0.048 rows=1 loops=1) │ 
│   Index Cond: (x @> '[3, "second item"]'::jsonb)              │ 
│ Planning time: 0.248 ms                      │ 
│ Execution time: 0.187 ms                      │ 
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 

缺點:

  • 沒有準備好值使用的功能/操作來刪除元素,只能通過索引。
  • 沒有現成的方法來檢查元素的唯一性,您需要自己創建它。

鏈接:
JSON Types
jsonb Indexing
JSON Functions and Operators

相關問題