Nee*_*pta 4 postgresql indexing pattern-matching jsonb
这是对jsonb键/值的模式匹配的后续跟进
我有一张桌子如下
CREATE TABLE "PreStage".transaction (
transaction_id serial NOT NULL,
transaction jsonb
CONSTRAINT pk_transaction PRIMARY KEY (transaction_id)
);
Run Code Online (Sandbox Code Playgroud)
我的事务jsonb列中的内容看起来像
{"ADDR": "abcd", "CITY": "abcd", "PROV": "",
"ADDR2": "",
"ADDR3": "","CNSNT": "Research-NA", "CNTRY": "NL", "EMAIL": "@.com",
"PHONE": "12345", "HCO_NM": "HELLO", "UNQ_ID": "",
"PSTL_CD": "1234", "HCP_SR_NM": "", "HCP_FST_NM": "",
"HCP_MID_NM": ""}
Run Code Online (Sandbox Code Playgroud)
我需要搜索查询,如:
SELECT transaction AS data FROM "PreStage".transaction
WHERE transaction->>'HCP_FST_NM' ILIKE '%neer%';
Run Code Online (Sandbox Code Playgroud)
但我需要让我的用户灵活地搜索任何键/值.
对上一个问题的回答建议将索引创建为:
CREATE INDEX idxgin ON "PreStage".transaction
USING gin ((transaction->>'HCP_FST_NM') gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)
哪个有效,但我也想索引其他键.因此尝试了类似的事情:
CREATE INDEX idxgin ON "PreStage".transaction USING gin
((transaction->>'HCP_FST_NM'),(transaction->>'HCP_LST_NM') gin_trgm_ops)
Run Code Online (Sandbox Code Playgroud)
哪个不起作用.这里最好的索引方法是什么,或者我必须为每个键创建一个单独的索引,在这种情况下,如果将新的键/值对添加到数据中,该方法将不是通用的.
@jjanes指出的语法错误,
对于一些流行键(包含在许多行中和/或经常搜索)以及许多更罕见的键(包含在少量行和/或很少搜索中),新键可能会动态弹出)我建议这个组合:
您似乎不会经常在一次搜索中组合多个键,并且具有多个键的单个索引将变得非常大且缓慢.所以我会为每个热门密钥创建一个单独的索引.使其成为大多数行中未包含的键的部分索引:
CREATE INDEX trans_idxgin_HCP_FST_NM ON transaction -- contained in most rows
USING gin ((transaction->>'HCP_FST_NM') gin_trgm_ops);
CREATE INDEX trans_idxgin_ADDR ON transaction -- not in most rows
USING gin ((transaction->>'ADDR') gin_trgm_ops)
WHERE transaction ? 'ADDR';
Run Code Online (Sandbox Code Playgroud)
等等.在我之前的回答中详细说明:
如果您有许多不同的键和/或动态添加新键,您可以使用基本(默认)jsonb_ops
GIN索引覆盖其余键:
CREATE INDEX trans_idxgin ON "PreStage".transaction USING gin (transaction);
Run Code Online (Sandbox Code Playgroud)
除此之外,这支持搜索键.但是你不能将它用于值的模式匹配.
结合处理两个索引的谓词:
SELECT transaction AS data
FROM "PreStage".transaction
WHERE transaction->>'HCP_FST_NM' ILIKE '%neer%'
AND transaction ? 'HCP_FST_NM'; -- even if that seems redundant.
Run Code Online (Sandbox Code Playgroud)
第二个条件恰好匹配我们的部分索引.
所以无论是有针对给定的(流行/通用)密钥的特定巽索引,或有至少找到包含稀土键(少数)的行的索引-然后筛选匹配的值.相同的查询应该给你两全其美.
一定要运行最新版本的Postgres,最近有成本估算的各种更新.Postgres使用良好的估计和当前的表统计信息来选择最佳查询计划至关重要.
没有内置索引可以精确执行您想要的操作,搜索精确的键和相应的通配符匹配值,而无需提前指定要使用的键。应该可以创建一个扩展来执行此操作,但这将是一项艰巨的工作,而且我不知道有任何扩展存在。
开箱即用的最佳选择可能是将 jsonb 转换为文本并索引该文本:
create index on transaction using gin ((transaction::text) gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)
然后向您的查询添加辅助条件:
SELECT transaction AS data FROM transaction
WHERE transaction->>'HCP_FST_NM' ILIKE '%neer%'
AND transaction::text ilike '%neer%';
Run Code Online (Sandbox Code Playgroud)
现在,它可以使用索引查找包含“neer”的任何内容,然后重新检查“neer”是否出现在“HCP_FST_NM”键的值中,而不是仅出现在JSONB
.
如果您的查询词出现在所需键值以外的许多地方,那么这可能不会给您带来很好的性能。例如,如果有人搜索:
transaction->>'EMAIL' ilike '%ADDR%'
AND transaction::text ilike '%ADDR%';
Run Code Online (Sandbox Code Playgroud)
假设所有记录具有与您显示的结构相同的结构,索引将返回每一行,因为每一行都包含“ADDR”,因为用作键。然后,每一行都会无法通过其他条件检查,但前提是做了很多工作之后。
归档时间: |
|
查看次数: |
2053 次 |
最近记录: |