大家好,欢迎来到IT知识分享网。
随着最新版本的PostgreSQL获得更多的JSON功能,我们被问及PostgreSQL是否可以将MongoDB替换为JSON数据库。有一个简短的答案,但我们宁愿向你展示。啊,来自观众的一个问题
“没有PostgreSQL已经有一些JSON支持?”
是的,它确实。在PostgreSQL 9.4之前有JSON数据类型,并且仍然可用。它可以让你这样做:
>CREATE TABLE justjson ( id INTEGER, doc JSON)>INSERT INTO justjson VALUES ( 1, '{ "name":"fred", "address":{ "line1":"52 The Elms", "line2":"Elmstreet", "postcode":"ES1 1ES" } }');
IT知识分享网
将JSON数据的原始文本存储在数据库中,并保留空白并保留所有键和任何重复键的所有命令。让我们看看数据显示:
IT知识分享网>SELECT * FROM justjson; id | doc----+--------------------------------- 1 | { + | "name":"fred", + | "address":{ + | "line1":"52 The Elms", + | "line2":"Elmstreet", + | "postcode":"ES1 1ES" + | } + | }(1 row)
它存储了源数据的精确副本。但是我们仍然可以从中提取数据。为此,有一组JSON运算符让我们引用JSON文档中的元素。所以说我们只是想要地址部分,我们可以这样做:
select doc->>'address' FROM justjson; ?column?--------------------------------- { + "line1":"52 The Elms", + "line2":"Elmstreet", + "postcode":"ES1 1ES" + }(1 row)
该->>
运营商表示文档中,查找JSON对象有以下字段名,并返回它作为文本。有了一个数字,它会把它当作一个数组索引,但是仍然以文本形式返回值。还有->
一起去->>
不这样做转换为文本。我们需要这样的,所以我们可以导航到这样的JSON对象:
IT知识分享网select doc->'address'->>'postcode' FROM justjson; ?column?---------- ES1 1ES(1 row)
虽然有一个更简短的形式,我们可以指定一个数据的路径,我们正在使用后#>>
,像这样的数组:
select doc#>>'{address,postcode}' FROM justjson; ?column?---------- ES1 1ES(1 row)
通过保留整个文档的JSON数据类型,可以轻松地处理JSON文档的精确副本,并在不丢失的情况下传递它们。但是,正确性会带来成本和效率的损失,因此无法进行索引。因此,虽然保存和解析JSON文档非常方便,但仍然有很大的改进余地,而且JSONB也是如此。
“JSONB有什么不同?
那么,使用JSONB将JSON文档转换为键/值数据对的层次结构。所有的空白都被丢弃,只有一组重复键中的最后一个值被使用,并且键的顺序会丢失到存储它们的散列所规定的结构中。如果我们创建一个我们刚创建的JSONB版本的表,插入一些数据并查看它:
>CREATE TABLE justjsonb ( id INTEGER, doc JSONB)>INSERT INTO justjsonb VALUES ( 1, '{ "name":"fred", "address":{ "line1":"52 The Elms", "line2":"Elmstreet", "postcode":"ES1 1ES" } }');>SELECT * FROM justjsonb; id | doc----+---------------------------------------------------------------------------------------------------- 1 | {"name": "fred", "address": {"line1": "52 The Elms", "line2": "Elmstreet", "postcode": "ES1 1ES"}}(1 row)
我们可以看到所有的textyness
数据已经消失了,取而代之的是JSON文档中保存的数据。这种剥离数据意味着JSONB表示将解析工作移动到插入数据的时候,但是解除了解析任务后的任何数据访问。
“这看起来有点像PostgreSQL中的HSTORE,虽然”
看作键/值对,那么JSONB数据类型看起来有点像PostgreSQL HSTORE扩展。这是用于存储键/值对的数据类型,但是它是JSONB(和JSON)在核心中的扩展,在JSON文档可以具有嵌套元素的数据结构方面,HSTORE是一个深度。此外,HSTORE只存储字符串,而JSONB理解字符串和全部的JSON数字。
“那么JSONB究竟给我带来了什么呢?”
索引,索引到处。你实际上不能在PostgreSQL中索引一个JSON数据类型。你可以使用表达式索引为它创建一个索引,但是这将会涵盖你在表达式中的任何东西。所以如果我们想要我们可以做的
create index justjson_postcode on justjson ((doc->'address'->>'postcode'));
和邮政编码,没有别的将被索引。
使用JSONB,支持GIN索引; 一个广义倒置索引。这为您提供了另一组查询运算符。这些@>
包含JSON,<@
包含,?
测试字符串存在,?|
任何字符串存在和?&
所有字符串存在。
有两种类型的索引可以使用缺省索引来创建,称为json_ops
索引,它支持所有这些操作符以及jsonb_path_ops
仅支持的索引@>
。默认索引为JSON中的每个键和值创建一个索引项,而jsonb_path_ops
唯一创建一个导致值和值本身的键的哈希值,这比更复杂的默认值更紧凑和更快处理。但是默认情况下提供了更多的操作,但消耗更多的空间。在向我们的表中添加一些数据之后,我们可以选择查找特定的邮政编码。如果我们创建默认的GIN JSON索引并执行查询:
explain select * from justjsonb where doc @> '{ "address": { "postcode":"HA36CC" } }'; QUERY PLAN----------------------------------------------------------------- Seq Scan on justjsonb (cost=0.00..3171.14 rows=100 width=123) Filter: (doc @> '{"address": {"postcode": "HA36CC"}}'::jsonb)(2 rows)
我们可以看到它会顺序扫描表格。现在,如果我们创建一个默认的JSON GIN索引,我们可以看到它的差异:
> create index justjsonb_gin on justjsonb using gin (doc);> explain select * from justjsonb where doc @> '{ "address": { "postcode":"HA36CC" } }'; QUERY PLAN------------------------------------------------------------------------------- Bitmap Heap Scan on justjsonb (cost=40.78..367.62 rows=100 width=123) Recheck Cond: (doc @> '{"address": {"postcode": "HA36CC"}}'::jsonb) -> Bitmap Index Scan on justjsonb_gin (cost=0.00..40.75 rows=100 width=0) Index Cond: (doc @> '{"address": {"postcode": "HA36CC"}}'::jsonb)(4 rows)
这是更有效的搜索,你可以告诉成本较低。但隐藏的成本是在指数的大小。在这种情况下,它是数据大小的41%。让我们删除该索引,并用jsonb_path_ops GIN索引重复该过程。
> create index justjsonb_gin on justjsonb using gin (doc jsonb_path_ops);> explain select * from justjsonb where doc @> '{ "address": { "postcode":"HA36CC" } }'; QUERY PLAN------------------------------------------------------------------------------- Bitmap Heap Scan on justjsonb (cost=16.78..343.62 rows=100 width=123) Recheck Cond: (doc @> '{"address": {"postcode": "HA36CC"}}'::jsonb) -> Bitmap Index Scan on justjsonb_gin (cost=0.00..16.75 rows=100 width=0) Index Cond: (doc @> '{"address": {"postcode": "HA36CC"}}'::jsonb)(4 rows)
总成本稍低,通常指数规模应该小很多。这将是平衡索引速度和大小的经典任务。但是它比顺序扫描更有效率。
“我应该用这个作为我的JSON数据库吗?”
如果你更新了你的JSON文件,答案是否定的。PostgreSQL非常擅长存储和检索JSON文档及其字段。但即使您可以单独处理JSON文档中的各个字段,也无法更新单个字段。那么,实际上你可以,但通过提取整个JSON文档,附加新的值并写回来,让JSON解析器整理重复。但是,你可能不想依赖这个。
如果你的活动数据在关系模式中舒适地存在,并且JSON内容是这个数据的一个队列,那么PostgreSQL应该没问题,而且它的JSONB表示和索引功能更有效率。如果您的数据模型是可变文档集合的数据模型,那么您可能要查看一个主要围绕像MongoDB或RethinkDB这样的JSON文档进行工程设计的数据库。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/6565.html