Postgresql

大量列或行的最佳數據庫

  • March 9, 2017

問題1:

我有一個包含 567 行和 16,382 列的文件,其中大部分是浮點數。我有另一個包含 117,493 行但只有 3 列的文件。內容涉及生物學和遺傳學。

我不知道文件中的數字是什麼意思。這是一個大學項目,我必須能夠在不知道內容是什麼的情況下查詢給定文件的不同內容。我假設我們不應該規範化數據,因為這需要理解內容。我們根據性能和選擇哪些數據庫的理由進行評分。

文件 1:(567 行,16,382 列)

我一直讓人們對這個文件中的列數感到驚訝。這些列大多是帶有一堆數字的遺傳資訊,無法標準化。我最初認為 Postgresql 對File 1有好處,但我讀到它們是一個面向行的數據庫,所以這太可怕了。我讀到 Cassandra 非常適合面向列的查找,但問題是大多數列和行都包含數據並且大部分是結構化的,除了一些沒有值的區域。使用 Cassandra 還是一個更好的主意嗎?

文件 1的操作:

  • 簡單的查找
  • 求均值
  • 找到標準差

我無法確認 SQL 和 NoSQL 在聚合函式(例如計算平均值和標準差)上的一般性能。所以這是選擇我的數據庫的另一個因素。我會假設 Cassandra 比 Postgresql 更快,因為 Cassandra 是面向列的。

文件 2:(117,493 行,3 列)

每一行和每一列都包含數據。我猜 Postgresql 在這裡很好,因為只有 3 列但 117,493 行,Postgresql 是面向行的,並且沒有失去數據。在這種情況下是否有更好的 NoSQL 替代方案?鍵值儲存 NoSQL 會更好嗎,因為它主要用於檢索?

文件 2的操作:

  • 簡單的查找

問題2:

我擁有的大多數大文件都通過某種 ID 相關聯,例如File 1File 2如果我對File 2使用 Postgresql ,對File 1使用Cassandra ,會不會有相當大的性能損失?通常您會將相關表儲存在 RDMS 中,但文件 1的列數是否意味著使用混合方法更好?

PostgreSQL

@Dobob 一切都可以標準化 :) 如果不是很秘密,它是什麼類型的數據?(作為一名遺傳學家出身的 DBA 提問。)

通常是正確的。你應該開始研究如何標準化。顯然你反對這個想法,你不能總是正常化。例如,柵格通常是來自科學儀器的讀數的集合,您無法真正對其進行非規範化。它們是同時採集的,代表相同的樣本,並且經常有 1,000 個數據點。(儘管現在您可以將它們儲存在 PostGIS 中)。

問題 1 的解決方案

PostgreSQL 不支持表上的 16,383 列(或超過 1,600+ 列),但它支持SQL Arrays。你可能可以利用它,

CREATE TABLE foo AS
 SELECT
   r AS id,
   array_agg(c) AS genetic_stuff
 FROM generate_series(1,567)
   AS r
 CROSS JOIN LATERAL generate_series(1,16382)
   AS c
 GROUP BY r;

現在您有一個符合第一個條件但並不瘋狂的表。

         Table "public.foo"
   Column     |   Type    | Modifiers 
---------------+-----------+-----------
id            | integer   | 
genetic_stuff | integer[] | 

求平均值很簡單..

SELECT id, avg(x)
FROM foo
CROSS JOIN LATERAL unnest(genetic_stuff)
 AS t(x)
GROUP BY id;

而對於整個操作Execution time: 3865.308 ms!可以投訴那個。MATERIALIZED VIEW如果您想記憶體該平均值,請隨意使用。

對於標準偏差,只需使用適當的聚合函式代替avg(). 執行時間大致相同。

我不確定你是如何在這裡查詢這個的,但是沒有索引(最壞的情況)非常簡單和快速(考慮到它是一個 seq 掃描)掃描一個包含 16,000 個項目的數組對於現代的 a CPU,在 PostgreSQL 9.6 上,這個 seq 掃描甚至應該並行執行(afaik)。

SELECT * FROM foo
WHERE genetic_stuff @> ARRAY[5];

可以使用索引嗎?當然。從intarray模組,

提供了兩個 GiST 索引運算符類:gist__int_ops(預設使用)適用於中小型數據集,而 gist__intbig_ops 使用較大的簽名,更適用於索引大型數據集(即包含大量不同的數組值)。該實現使用具有內置有損壓縮的 RD-tree 資料結構。

讓我們試一試…

CREATE INDEX ON foo
 USING gist(genetic_stuff gist__intbig_ops);
VACUUM FULL foo;

                                                         QUERY PLAN                                                           
-------------------------------------------------------------------------------------------------------------------------------
Index Scan using foo_genetic_stuff_idx on foo  (cost=0.14..8.16 rows=1 width=22) (actual time=0.119..47.846 rows=567 loops=1)
  Index Cond: (genetic_stuff @> '{5}'::integer[])
Planning time: 0.072 ms
Execution time: 47.948 ms
(4 rows)

不知道你想要什麼而不是索引掃描。如果不是每一行都有一個元素,可能會更有用5,但您知道它只是範例數據。

反正有它。

問題 2 的解決方案

害羞的是,另一件事根本不是問題,因為 Pg 行很胖,但你不是在說很多行,最終它應該不重要,下面的表格滿足標準只有 5088 kB我的系統。幾乎不值得關心自己。

CREATE TABLE baz
AS
 SELECT
   x AS id,
   x*2 AS x2,
   x*3 AS x3,
   x*4 AS x4
 FROM generate_series(1,117493)
   AS t(x);

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