閱讀72 返回首頁    go 阿裏雲 go 技術社區[雲棲]


PostgreSQL schemaless 的實現(類mongodb collection)

標簽

PostgreSQL , schemaless , mongodb


背景

使用mongodb時,並不需要先建表(collection),直接就可以往裏麵寫,原因是collection本事就是固定的BSON結構。

所以當用戶插入時,如果表不存在,建一個BSON結構的colleciton即可。

而關係數據庫無法做到這一點,因為關係數據庫的表結構都是事先構建,並且在寫入數據時,是需要檢查對應的類型,約束的。

那麼有沒有辦法讓PostgreSQL關係數據庫也實現類似mongo這種schemaless的表呢?

函數式寫入

用戶通過調用函數,寫入數據。

在函數中處理並實現schemaless。

例子

創建一個自動建表的函數,用於自動創建目標表。

create or replace function create_schemaless(target name) returns void as $$  
declare  
begin  
  execute format('create table if not exists %I (content jsonb)', target);  
exception when others then  
  return;  
end;  
$$ language plpgsql strict;  

創建一個插入數據的函數,使用動態SQL,如果遇到表不存在的錯誤,則調用建表函數進行建表。

create or replace function ins_schemaless(target name, content jsonb) returns void as $$  
declare  
begin  
  execute format('insert into %I values (%L)', target, content);  
  exception   
    WHEN SQLSTATE '42P01' THEN   
    perform create_schemaless(target);  
    execute format('insert into %I values (%L)', target, content);   
end;  
$$ language plpgsql strict;  

調用函數插入數據,不需要建表,會自動創建。

postgres=# select ins_schemaless('abcde','{"a":123.1}');  
 ins_schemaless   
----------------  
   
(1 row)  
  
postgres=# select * from abcde;  
   content      
--------------  
 {"a": 123.1}  
(1 row)  
  
postgres=# select ins_schemaless('abcde','{"a":123.1}');  
 ins_schemaless   
----------------  
   
(1 row)  
  
postgres=# select * from abcde;  
   content      
--------------  
 {"a": 123.1}  
 {"a": 123.1}  
(2 rows)  
  
postgres=# select ins_schemaless('abcdefg','{"a":123.1}');  
 ins_schemaless   
----------------  
   
(1 row)  
  
postgres=# select * from abcdefg;  
   content      
--------------  
 {"a": 123.1}  
(1 row)  

函數支持並發插入,不會相互影響。

性能

由於使用了動態SQL,性能略差。

transaction type: ./test.sql  
scaling factor: 1  
query mode: prepared  
number of clients: 32  
number of threads: 32  
duration: 120 s  
number of transactions actually processed: 26908558  
latency average = 0.143 ms  
latency stddev = 1.397 ms  
tps = 224219.413026 (including connections establishing)  
tps = 224353.960206 (excluding connections establishing)  
script statistics:  
 - statement latencies in milliseconds:  
         0.143  select ins_schemaless('c','{}');  

使用綁定變量,性能如下。

transaction type: ./test.sql  
scaling factor: 1  
query mode: prepared  
number of clients: 32  
number of threads: 32  
duration: 120 s  
number of transactions actually processed: 39684200  
latency average = 0.097 ms  
latency stddev = 2.192 ms  
tps = 330698.368601 (including connections establishing)  
tps = 330708.294542 (excluding connections establishing)  
script statistics:  
 - statement latencies in milliseconds:  
         0.097  insert into c values ('{}');  

損失11萬的QPS,獲得schemaless的能力,要不要呢?

當然,如果是從內核層麵來支持就更爽了,性能問題可能也能得到解決,比如。

insert into schemaless tbl values (jsonb);  

最後更新:2017-05-13 08:43:04

  上一篇:go  測試
  下一篇:go  在Oracle專家眼中,MySQL sys Schema是怎樣一種存在?