例如,假设我有一个中等行数(约 100,000 行)的表,其中一jsonb列包含以下示例数据:
{"name":"Bob", "favoriteColor":"red", "someOtherObject": {"somethingElse": true}}
Run Code Online (Sandbox Code Playgroud)
是否更有效:
在 jsonb 列上使用 GIN 索引,然后使用 Postgres 的内置 JSON 查询函数来提取数据
创建多列来表示可以搜索的内容,即一列用于name,一列用于favoriteColor等;在这些列上构建 b 树索引,然后运行select document from table where name = 'Bob'
一些其他的解决方案?
请记住,解决方案需要有效地支持like查询,以便能够搜索以给定输入字符串开头的值。
我有一个表定义为:
create table dummy (jdata jsonb);
Run Code Online (Sandbox Code Playgroud)
我插入了以下两行:
insert into dummy values ('["dog","cat","elephant","waffle"]');
insert into dummy values ('[1,2,3,4]');
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用 jsonb?&运算符,它可以让您提出问题“所有这些键/元素字符串都存在吗?”
使用字符串字段的示例有效:
select * from dummy where jdata ?& array['cat','dog'];
jdata
--------------------------------------
["dog", "cat", "elephant", "waffle"]
(1 row)
Run Code Online (Sandbox Code Playgroud)
但是,尝试使用包含数字的数组来执行此操作是行不通的:
select * from dummy where jdata ?& array['1','2'];
jdata
-------
(0 rows)
select * from dummy where jdata ?& array['1','2'];
jdata
-------
(0 rows)
select * from dummy where jdata ?& array[1,2];
ERROR: operator does not exist: jsonb ?& integer[]
LINE …Run Code Online (Sandbox Code Playgroud) 我正在尝试JSONB与 JDBC一起使用,这意味着我必须避免使用任何使用 '?' 的运算符。字符(因为 PostgreSQL JDBC 驱动程序没有对该字符进行转义)。拿一个简单的表格:
CREATE TABLE jsonthings(d JSONB NOT NULL);
INSERT INTO jsonthings VALUES
('{"name":"First","tags":["foo"]}')
, ('{"name":"Second","tags":["foo","bar"]}')
, ('{"name":"Third","tags":["bar","baz"]}')
, ('{"name":"Fourth","tags":["baz"]}');
CREATE INDEX idx_jsonthings_name ON jsonthings USING GIN ((d->'name'));
Run Code Online (Sandbox Code Playgroud)
使用命令行我可以运行一个简单的选择并按预期使用索引:
EXPLAIN ANALYZE SELECT d FROM jsonthings WHERE d->'name' ? 'First';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on jsonthings (cost=113.50..30236.13 rows=10000 width=61) (actual time=0.024..0.025 rows=1 loops=1)
Recheck Cond: ((d -> 'name'::text) ? 'First'::text)
Heap Blocks: exact=1
-> Bitmap Index Scan on idx_jsonthings_name (cost=0.00..111.00 rows=10000 width=0) (actual …Run Code Online (Sandbox Code Playgroud) 我正在想办法构建一个新的 PostgreSQL 数据库,我很好奇是否可以使用 JSONB 列而不是 EAV 模型来存储实体的属性。这似乎是一种灵活的方式来存储这些东西。
在 EAV 情况下,我将有 3 个表:
materials (mat_id, mat_name, mat_descr)
material_properties (prop_id, prop_name, prop_desc)
material_property_values (mat_id, prop_id, val)
Run Code Online (Sandbox Code Playgroud)
每种材料都可以有一组不同的属性。
有什么原因我不应该只mat_props JSONB在我的materials表中添加一列,并将所有属性存储在那里{"name":"value"}?这样,将属性作为列进行查询将非常简单:
SELECT mat_name, mat_props->'name' as propval FROM materials
Run Code Online (Sandbox Code Playgroud)
而不是连接或子选择。
另外,我是否可以在materials表中添加此列,或者将其保存在单独的表中是否会更高效:
material_properties (mat_id, properties JSONB)
Run Code Online (Sandbox Code Playgroud) 我使用的是 PG 9.5,我有一个表 Visitor(id, data::json)
例子:
Visitor(id: 1, data: {name: 'Jack', age: 33, is_user: true })
Run Code Online (Sandbox Code Playgroud)
我想执行类似的查询
数据列内的键是用户指定的,因此是动态的。
在这种情况下哪个索引最有意义?
我有一个包含类似于此对象的 json 数组的表:
id | record
____________________
name1 | [{"a":0, "b":x}, {"a":1, "b":y}, {"a":2, "b":z}, ...]
Run Code Online (Sandbox Code Playgroud)
我想得到一个包含仅包含“a”值的 json 数组的表:
id | record
____________________
name1 | [0, 1, 2, ...]
Run Code Online (Sandbox Code Playgroud)
我使用的是 PostgreSQL 11,所以最新的功能是可以接受的。
我正在测试 MySQLJSON_ARRAY和JSON_ARRAYAGG函数,以便将一些应用程序昂贵的进程移动到 SQL 存储函数。
在下面的电子商务应用程序示例中,我尝试检索用户的购物车,而不是作为来自 cart_items 表的行结果集,而是作为包含 Javascript 回调函数呈现购物车所需的所有信息的 JSON 字符串。
我有一张cart包含一般购物车信息的表格
create table user_cart (
cart_id integer unsigned primary key,
user_id integer unsigned not null,
);
Run Code Online (Sandbox Code Playgroud)
和cart_item明细表,
create table cart_item (
cart_item_id integer unsigned primary key auto_increment,
cart_id integer unsigned not null,
product_id integer unsigned not null,
qty integer unsigned not null,
ref varchar(15) not null,
-- total
base double default 0.0,
tax double default 0.0,
tax_pct double default 0.0,
total …Run Code Online (Sandbox Code Playgroud) 当表具有 json 或 jsonb 列时,是否无法在 INSERT/UPDATE 触发器中进行全行比较?我收到的错误让我认为我需要单独比较每一列,因为该NEW.*/OLD.*格式不能用于比较 json 列。
CREATE OR REPLACE FUNCTION on_insert_update_modified()
RETURNS TRIGGER AS $$
BEGIN
IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
NEW.modified_at = now();
RETURN NEW;
ELSE
RETURN OLD;
END IF;
END;
$$ language 'plpgsql';
CREATE TRIGGER mytable_insert_update
BEFORE INSERT OR UPDATE ON mytable
FOR EACH ROW
EXECUTE PROCEDURE on_insert_update_modified();
Run Code Online (Sandbox Code Playgroud)
当我插入包含 json 和 jsonb 列的表时,出现以下错误:
CREATE OR REPLACE FUNCTION on_insert_update_modified()
RETURNS TRIGGER AS $$
BEGIN
IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
NEW.modified_at …Run Code Online (Sandbox Code Playgroud) 我正在尝试构建一个查询,该查询会生成一个由 SQL Server 生成的 JSON 对象。我发现我可以使用子查询用包含问题列表的 JSON 字符串填充字段(在本例中为问题字段)。
下面是查询:
SELECT
quizzes.id AS 'id',
quizzes.name AS 'name',
quizzes.description AS 'description',
quizzes.instructions AS 'instructions',
author.id AS 'author.id',
author.midas AS 'author.midas',
author.first_name AS 'author.first_name',
author.last_name AS 'author.last_name',
author.email AS 'author.email',
author.tel AS 'author.tel',
author.department_name AS 'author.department_name',
author.created_at AS 'author.created_at',
author.last_updated AS 'author.last_updated',
course.id AS 'course.id',
course.name AS 'course.name',
course.description AS 'course.description',
course.crn AS 'course.crn',
instructor.id AS 'course.instructor.id',
instructor.midas AS 'course.instructor.midas',
instructor.first_name AS 'course.instructor.first_name',
instructor.last_name AS 'course.instructor.last_name',
instructor.email AS 'course.instructor.email',
instructor.tel AS 'course.instructor.tel',
instructor.department_name …Run Code Online (Sandbox Code Playgroud) 我在“资产”表中有一个名为“参数”的 json 列。json 是嵌套的并具有以下结构:
{
"params1": {"k": 1.1, "efficiency": 0.7},
"params2": {"k": 1.9, "C_max": 100.0, "C_min": 10.0}
}
Run Code Online (Sandbox Code Playgroud)
我只想更新“params2”中的一个值“k”,并保持其余值不变。我尝试使用以下代码:
update "Assets"
set "Parameters" = "Parameters"::jsonb || '{"params2":{"k":2.2}}'::jsonb
where "Id" = 185;
Run Code Online (Sandbox Code Playgroud)
这导致
{
"params1": {"k": 1.1, "efficiency": 0.7},
"params2": {"k": 2.2}
}
Run Code Online (Sandbox Code Playgroud)
因此“params2”中的其余参数被删除,这是不希望的。修改“k”并保持其余部分不变的方法是什么?
json ×10
postgresql ×8
array ×2
index ×2
eav ×1
index-tuning ×1
mysql ×1
operator ×1
plpgsql ×1
query ×1
sql-server ×1
subquery ×1
trigger ×1