2017-09-10 75 views
11

Po uruchomieniu PostgreSQL 9.6.4 na moim laptopie, mam tabelę o nazwie node, która ma pole klucza podstawowego id i pole properties::jsonb.Optymalizacja zapytań przy użyciu pola JSON

Mam ustawienia indeksu GIN w polu properties.

Kiedy uruchomić tę kwerendę:

SELECT n.* 
FROM  node n 
WHERE node_type_id = '2' 
AND  properties @> '{"slug":"wild-castles"}'::JSONB 
ORDER BY n.id ASC OFFSET 0 LIMIT 10; 

na ~ 5M wierszy tabeli To trwa około 20 sekund, aby uzyskać odpowiedź. Patrząc na planie wyjaśnić I okazało się, że optymalizator kwerendy jest pierwszy sortowania tabeli przez klucz podstawowy, a następnie filtrowany przez pole properties:

Limit (cost=0.56..1517.94 rows=10 width=154) 
    -> Index Scan using node_pkey on node n (cost=0.56..739571.11 rows=4874 width=154) 
     Filter: ((properties @> '{"slug": "wild-castles"}'::jsonb) AND ((node_type_id)::text = '2'::text)) 

Ale kiedy usunąć kolejność widzę optymalizator używając indeksu zgodnie z oczekiwaniami:

SELECT n.* 
FROM node n 
WHERE node_type_id = '2' 
AND properties @> '{"slug":"wild-castles"}'::JSONB 
OFFSET 0 LIMIT 10; 

Limit (cost=93.77..127.10 rows=10 width=154) 
    -> Bitmap Heap Scan on node n (cost=93.77..16338.56 rows=4874 width=154) 
     Recheck Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 
     Filter: ((node_type_id)::text = '2'::text) 
     -> Bitmap Index Scan on node_ix02 (cost=0.00..92.55 rows=4874 width=0) 
       Index Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 

również proste WHERE properties @> '{"slug":"wild-castles"}'::JSONB zachowuje się zgodnie z oczekiwaniami:

EXPLAIN SELECT n.* 
FROM  node n 
WHERE properties @> '{"slug":"wild-castles"}'::JSONB 
; 

Bitmap Heap Scan on node n (cost=93.77..16326.38 rows=4874 width=154) 
    Recheck Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 
    -> Bitmap Index Scan on node_ix02 (cost=0.00..92.55 rows=4874 width=0) 
     Index Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 

Więc myślę, zastanawiam się dlaczego wo i czy optymalizator nie użyje indeksu do odfiltrowania pierwszych wierszy, a następnie uporządkowania ich przez pole id?

+0

Jakie są szacunkowe dane dla prostego 'where properties @> '{" slug ":" wild-zamki "}' :: JSONB'? – teppic

+0

Zaktualizowałem pytanie. – acohen

+0

Jaki procent węzłów ma pole "Ślimak"? Jaki procent tych węzłów ma atrybut "ślimaka" z wartością "dzwony". – teppic

Odpowiedz

1

Zmień Planner Method Configuration i siła planer się nie robić seqscan

np

 SET enable_seqscan = OFF; 

     SELECT n.* 
     FROM  node n 
       WHERE node_type_id = '2' 
       AND  properties @> '{"slug":"wild-castles"}'::JSONB 
      ORDER BY n.id ASC OFFSET 0 LIMIT 10; 
1

Z mojego doświadczenia wynika, czasami trzeba oszukać planner zapytania, aby ją wykonywać dobrze, a to zajmuje trochę szczypanie i błahy z ...

chciałbym spróbować działa to, aby zobaczyć jak to działa:

SELECT nn.* FROM (
    SELECT n.* 
    FROM node n 
    WHERE node_type_id = '2' 
    AND properties @> '{"slug":"wild-castles"}'::JSONB 
) nn 
ORDER BY nn.id ASC OFFSET 0 LIMIT 10;