我對postgres相當陌生,目前使用的是9.6。 當試圖使用它的jsonb文檔在postgres中實現全文搜索時,我注意到嵌套數組的搜索結果慢。我使用'explain'命令,它沒有使用任何索引。 爲了簡化目的,我創建了一個表,調查:在PostgreSQL中搜索嵌套JSONB數組元素的索引
CREATE TABLE book (
id BIGSERIAL NOT NULL,
data JSONB NOT NULL
);
我的可用指標:
CREATE INDEX book_author_idx
ON book USING GIN (to_tsvector('english', book.data ->> 'author'));
CREATE INDEX book_author_name_idx
ON book USING GIN (to_tsvector('english', book.data -> 'author' ->> 'name'));
和一些數據來填充文件:
INSERT INTO book (data)
VALUES (CAST('{"author": [{"id": 0, "name": "Cats"}, ' ||
' {"id": 1, "name": "Dogs"}]}' AS JSONB));
我能搜索對於使用以下查詢的圖書元素,但它不使用任何索引。我的實際數據爲12萬個產品,大約需要1200毫秒,而其他索引則需要0.2毫秒。
EXPLAIN ANALYZE
SELECT
id,
data ->> 'author' AS author
FROM book, jsonb_array_elements(data #> '{author}') author_array
WHERE to_tsvector('english', author_array ->> 'name') @@ to_tsquery('cat');
相反下一查詢使用book_author_name_idx但由於陣列結構沒有找到任何東西。
EXPLAIN ANALYZE
SELECT
id,
data ->> 'author' AS author
FROM book
WHERE to_tsvector('english', data -> 'author' ->> 'name') @@ to_tsquery('cat');
如何調整我的查詢以使用語言索引? 我知道,我可以爲作者創建一個新表格,並只引用id,但我寧願將所有數據保存在一張表中以獲得性能。
在'LATERAL JOIN'中使用'unnest()'和它的朋友(結果集生成函數,如'jsonb_array_elements()')可以防止使用任何索引(至少是從它們算出的屬性)。如果你堅持這種結構,你必須創建一個自定義的'IMMUTABLE'函數來從你的'jsonb'列中產生'tsvector'值並在你的索引和查詢中使用這個函數。 – pozs
這裏有趣的部分是'tsvector'沒有任何內置的聚合,所以你需要1)將名稱聚合爲字符串(帶有一些基本規則)2)爲'tsvector'構建一個自定義聚合3 )使用一個聰明的遞歸CTE(因爲他們已經存在連接)。 – pozs