Postgres JSONB - 两个JSON字段之间的连接

问题描述 投票:2回答:1

使用Postgres 9.5,如何查询具有JSONB列的表,加入两个JSON字段,关键是利用GIN索引来最大化性能?

我正在为一个系统进行原型设计,该系统可以在一个平台上为不同的客户提供不同的模式/数据模型。实体 - 属性 - 值(EAV)是一种常见的模式,我很想对Postgres如何处理使用其JSONB数据类型存储的实体的查询进行基准测试。

我有一个表存储不同类型的实体,例如客户,销售交易。

CREATE TABLE entity_jsonb (
    id uuid PRIMARY KEY,
    type text,
    created_at timestamp without time zone,
    properties jsonb,
    org_id integer
);
CREATE INDEX entity_jsonb_created_at_idx ON entity_jsonb USING btree (created_at);
CREATE INDEX entity_jsonb_org_id_idx ON entity_jsonb USING btree (org_id);
CREATE INDEX entity_jsonb_type_idx ON entity_jsonb USING btree (type);
CREATE INDEX entity_jsonb_properties_idx ON entity_jsonb USING gin (properties);

我在此表中有一个客户记录,其类型为“客户”和属性:

{"uuid": "8f8896c7-f41c-49f7-ad6e-4613f7b51a23", "email": "[email protected]", "lastname": "McCarthy", "createdAt": "May 27, 2015 12:06:45 PM", "firstname": "Nathan"}

我在此表中有一个销售交易记录,类型为'sales_transaction'和属性:

{"uuid": "54243d48-e69f-4bb6-ab33-6defb8a0f626", "amount": 99817, "status": 0, "paymentType": 1, "currencyCode": "USD", "customerUuid": "8f8896c7-f41c-49f7-ad6e-4613f7b51a23", "transactionId": "471170"}

如何利用GIN索引(运算符:@>,?,?&,?|)有效地查询事务,但是与客户联系以从两者返回数据。填充过去7天的交易清单,显示客户名称和交易金额?

我已经尝试过这个查询来查找事务对象的子集(对于amount = 99817)和相关的客户详细信息:

SELECT t.properties AS transaction, c.properties AS customer 
FROM entity_jsonb t 
JOIN entity_jsonb c ON (c.properties->>'uuid' = t.properties->>'customerUuid' AND c.type = 'customer') 
WHERE t.type = 'sales_transaction' AND t.properties @> '{"amount" : 99817}';

它可以工作,但它没有使用GIN索引,即没有我想要的那么快。我尝试了这种方法(使用GIN @>包含运算符),但它不包括客户详细信息。我究竟做错了什么?

SELECT t.properties AS transaction, c.properties AS customer FROM entity_jsonb t LEFT JOIN entity_jsonb c ON (c.properties @> json_build_array(json_build_object('uuid', t.properties->'customerUuid'))::jsonb AND c.type = 'customer') WHERE t.type = 'sales_transaction' AND t.properties @> '{"amount" : 99817}';

我理解,与传统的关系设计相比,这不是一个最佳解决方案,但我很想知道查询如何有效地将实体数据纯粹存储为JSON。

postgresql postgresql-9.4
1个回答
3
投票

我的询问并不遥远。我不需要json_build_array。对于100k客户的数据集,查询现在运行速度比不使用GIN索引的版本快10倍:

SELECT t.properties AS transaction, c.properties AS customer 
FROM entity_jsonb t 
JOIN entity_jsonb c ON (c.properties @> json_build_object('uuid', t.properties->'customerUuid')::jsonb AND c.type = 'customer') 
WHERE t.type = 'sales_transaction' AND t.properties @> '{"amount" : 99817}';
© www.soinside.com 2019 - 2024. All rights reserved.